Skip to content

Commit a9fdf3d

Browse files
mhagstrandkrakjoe
authored andcommitted
Fix for Bug 74196: PharData->decompress() does not correctly support dot names
1. Fixed phar_rename_archive to no longer remove everything after a "." in the filename 2. Removed unused "zend_bool compress" parameter 3. Added Test 4. Fixed tests that had a work around for this problem
1 parent b0f9dba commit a9fdf3d

File tree

8 files changed

+94
-20
lines changed

8 files changed

+94
-20
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,8 @@ PHP NEWS
140140

141141
- phar:
142142
. Fixed bug #74383 phar method parameters reflection correction. (mhagstrand)
143+
. Fixed bug #74196 (phar does not correctly handle names containing dots).
144+
(mhagstrand)
143145

144146
- PHPDBG
145147
. Added extended_value to opcode dump output. (Sara)

ext/phar/phar_object.c

Lines changed: 55 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2019,7 +2019,7 @@ static int phar_copy_file_contents(phar_entry_info *entry, php_stream *fp) /* {{
20192019
}
20202020
/* }}} */
20212021

2022-
static zend_object *phar_rename_archive(phar_archive_data **sphar, char *ext, zend_bool compress) /* {{{ */
2022+
static zend_object *phar_rename_archive(phar_archive_data **sphar, char *ext) /* {{{ */
20232023
{
20242024
const char *oldname = NULL;
20252025
phar_archive_data *phar = *sphar;
@@ -2031,10 +2031,29 @@ static zend_object *phar_rename_archive(phar_archive_data **sphar, char *ext, ze
20312031
char *error;
20322032
const char *pcr_error;
20332033
int ext_len = ext ? strlen(ext) : 0;
2034-
size_t new_len, oldname_len;
2034+
size_t new_len, oldname_len, phar_ext_len;
20352035
phar_archive_data *pphar = NULL;
20362036
php_stream_statbuf ssb;
20372037

2038+
int phar_ext_list_len, i = 0;
2039+
char *ext_pos = NULL;
2040+
/* Array of PHAR extensions, Must be in order, starting with longest
2041+
* ending with the shortest. */
2042+
char *phar_ext_list[] = {
2043+
".phar.tar.bz2",
2044+
".phar.tar.gz",
2045+
".phar.php",
2046+
".phar.bz2",
2047+
".phar.zip",
2048+
".phar.tar",
2049+
".phar.gz",
2050+
".tar.bz2",
2051+
".tar.gz",
2052+
".phar",
2053+
".tar",
2054+
".zip"
2055+
};
2056+
20382057
if (!ext) {
20392058
if (phar->is_zip) {
20402059

@@ -2091,20 +2110,48 @@ static zend_object *phar_rename_archive(phar_archive_data **sphar, char *ext, ze
20912110
return NULL;
20922111
}
20932112

2094-
if (ext[0] == '.') {
2095-
++ext;
2096-
}
20972113

20982114
oldpath = estrndup(phar->fname, phar->fname_len);
20992115
if ((oldname = zend_memrchr(phar->fname, '/', phar->fname_len))) {
21002116
++oldname;
21012117
} else {
21022118
oldname = phar->fname;
21032119
}
2104-
oldname_len = strlen(oldname);
21052120

2121+
oldname_len = strlen(oldname);
2122+
/* Copy the old name to create base for the new name */
21062123
basename = estrndup(oldname, oldname_len);
2107-
spprintf(&newname, 0, "%s.%s", strtok(basename, "."), ext);
2124+
2125+
phar_ext_list_len = sizeof(phar_ext_list)/sizeof(phar_ext_list[0]);
2126+
/* Remove possible PHAR extensions */
2127+
/* phar_ext_list must be in order of longest extension to shortest */
2128+
for (i=0; i < phar_ext_list_len; i++) {
2129+
phar_ext_len = strlen(phar_ext_list[i]);
2130+
if (phar_ext_len && oldname_len > phar_ext_len) {
2131+
/* Check if the basename strings ends with the extension */
2132+
if (memcmp(phar_ext_list[i], basename + (oldname_len - phar_ext_len), phar_ext_len) == 0) {
2133+
ext_pos = basename + (oldname_len - phar_ext_len);
2134+
ext_pos[0] = '\0';
2135+
break;
2136+
}
2137+
}
2138+
ext_pos = NULL;
2139+
}
2140+
2141+
/* If no default PHAR extension found remove the last extension */
2142+
if (!ext_pos) {
2143+
ext_pos = strrchr(basename, '.');
2144+
if (ext_pos) {
2145+
ext_pos[0] = '\0';
2146+
}
2147+
}
2148+
ext_pos = NULL;
2149+
2150+
if (ext[0] == '.') {
2151+
++ext;
2152+
}
2153+
/* Append extension to the basename */
2154+
spprintf(&newname, 0, "%s.%s", basename, ext);
21082155
efree(basename);
21092156

21102157
basepath = estrndup(oldpath, (strlen(oldpath) - oldname_len));
@@ -2321,7 +2368,7 @@ static zend_object *phar_convert_to_other(phar_archive_data *source, int convert
23212368
phar_add_virtual_dirs(phar, newentry.filename, newentry.filename_len);
23222369
} ZEND_HASH_FOREACH_END();
23232370

2324-
if ((ret = phar_rename_archive(&phar, ext, 0))) {
2371+
if ((ret = phar_rename_archive(&phar, ext))) {
23252372
return ret;
23262373
} else {
23272374
if(phar != NULL) {

ext/phar/tests/bug48377.2.phpt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ $fname = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.zip';
1212
$phar = new PharData($fname);
1313
$phar['x'] = 'hi';
1414
try {
15-
$phar->convertToData(Phar::ZIP, Phar::NONE, '.2.phar.zip');
15+
$phar->convertToData(Phar::ZIP, Phar::NONE, 'phar.zip');
1616
} catch (BadMethodCallException $e) {
1717
echo $e->getMessage(),"\n";
1818
}
@@ -21,5 +21,5 @@ try {
2121
--CLEAN--
2222
<?php unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.zip');?>
2323
--EXPECTF--
24-
data phar "%sbug48377.2.phar.zip" has invalid extension 2.phar.zip
25-
===DONE===
24+
data phar "%sbug48377.2.phar.zip" has invalid extension phar.zip
25+
===DONE===
288 Bytes
Binary file not shown.

ext/phar/tests/bug74196.phpt

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
--TEST--
2+
PHP bug #74196: PharData->decompress() does not correctly support dot names
3+
--SKIPIF--
4+
<?php if (!extension_loaded("phar")) die("skip"); ?>
5+
<?php if (!extension_loaded("zlib")) die("skip"); ?>
6+
--INI--
7+
phar.require_hash=0
8+
phar.readonly=0
9+
--FILE--
10+
<?php
11+
$fname = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.1.2.3.phar.tar.gz';
12+
$decompressed_name = str_replace( ".gz", "", $fname);
13+
var_dump(file_exists($fname));
14+
15+
$phar = new Phar($fname);
16+
$phar->decompress();
17+
var_dump(file_exists($decompressed_name));
18+
unlink($decompressed_name);
19+
20+
?>
21+
--EXPECTF--
22+
bool(true)
23+
bool(true)

ext/phar/tests/phar_convert_repeated.phpt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,10 +91,10 @@ var_dump($phar->getAlias());
9191
unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.phar.zip');
9292
unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.phar.tar');
9393
unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.phar');
94-
unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.2.phar.zip');
95-
unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.2.phar.tar');
94+
unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.2.2.phar.zip');
95+
unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.2.2.2.phar.tar');
9696
unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.2.phar');
97-
unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.3.phar.zip');
97+
unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.2.2.2.3.phar.zip');
9898
unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.3.phar.tar');
9999
unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.3.phar');
100100
?>

ext/phar/tests/phar_convert_repeated_b.phpt

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,17 +74,19 @@ try {
7474
} catch(Exception $e) {
7575
echo $e->getMessage()."\n";
7676
}
77-
7877
?>
7978
===DONE===
8079
--CLEAN--
81-
<?php
80+
<?php
81+
echo dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.phar.gz' . "\n";
82+
8283
unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.phar.gz');
8384
unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.tar.gz');
8485
unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.tar');
85-
unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.2.tar');
86+
unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.1.2.tar');
8687
unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.zip');
8788
unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.1.zip');
89+
8890
?>
8991
--EXPECT--
9092
=================== new PharData() ==================
@@ -115,4 +117,4 @@ string(0) ""
115117
NULL
116118
================= convertToPhar() ====================
117119
Cannot write out executable phar archive, phar is read-only
118-
===DONE===
120+
===DONE===

ext/phar/tests/stat2_5.3.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ $fname2 = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.tar';
1717
$fname3 = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.tar';
1818
copy(dirname(__FILE__) . '/tar/files/links.tar', $fname2);
1919
$a = new PharData($fname2);
20-
$b = $a->convertToExecutable(Phar::TAR, Phar::NONE, '.3.phar.tar');
20+
$b = $a->convertToExecutable(Phar::TAR, Phar::NONE, '.phar.tar');
2121
unset($a);
2222
Phar::unlinkArchive($fname2);
2323
$b['foo/stat.php'] = '<?php
@@ -58,4 +58,4 @@ bool(false)
5858
dir
5959
bool(true)
6060
bool(false)
61-
===DONE===
61+
===DONE===

0 commit comments

Comments
 (0)