]> granicus.if.org Git - php/commitdiff
Fix for Bug 74196: PharData->decompress() does not correctly support dot names
authorMitch Hagstrand <mhagstrand@gmail.com>
Fri, 7 Apr 2017 23:52:12 +0000 (16:52 -0700)
committerJoe Watkins <krakjoe@php.net>
Mon, 10 Apr 2017 05:43:26 +0000 (06:43 +0100)
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

NEWS
ext/phar/phar_object.c
ext/phar/tests/bug48377.2.phpt
ext/phar/tests/bug74196.1.2.3.phar.tar.gz [new file with mode: 0644]
ext/phar/tests/bug74196.phpt [new file with mode: 0644]
ext/phar/tests/phar_convert_repeated.phpt
ext/phar/tests/phar_convert_repeated_b.phpt
ext/phar/tests/stat2_5.3.phpt

diff --git a/NEWS b/NEWS
index a69bdc846fa4a19887398f040dced0d1b14e062f..eae6a812885030f3aa8f4746c08c5305436d12ef 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -140,6 +140,8 @@ PHP                                                                        NEWS
 
 - phar:
   . Fixed bug #74383 phar method parameters reflection correction. (mhagstrand)
+  . Fixed bug #74196 (phar does not correctly handle names containing dots).
+    (mhagstrand)
 
 - PHPDBG
   . Added extended_value to opcode dump output. (Sara)
index 8e9233ae174c8e024a000190e2ecbc066c852903..f5973b5b273706d0bf07ba8e06755f29ddb1523a 100644 (file)
@@ -2019,7 +2019,7 @@ static int phar_copy_file_contents(phar_entry_info *entry, php_stream *fp) /* {{
 }
 /* }}} */
 
-static zend_object *phar_rename_archive(phar_archive_data **sphar, char *ext, zend_bool compress) /* {{{ */
+static zend_object *phar_rename_archive(phar_archive_data **sphar, char *ext) /* {{{ */
 {
        const char *oldname = NULL;
        phar_archive_data *phar = *sphar;
@@ -2031,10 +2031,29 @@ static zend_object *phar_rename_archive(phar_archive_data **sphar, char *ext, ze
        char *error;
        const char *pcr_error;
        int ext_len = ext ? strlen(ext) : 0;
-       size_t new_len, oldname_len;
+       size_t new_len, oldname_len, phar_ext_len;
        phar_archive_data *pphar = NULL;
        php_stream_statbuf ssb;
 
+       int phar_ext_list_len, i = 0;
+       char *ext_pos = NULL;
+       /* Array of PHAR extensions, Must be in order, starting with longest
+        * ending with the shortest. */
+       char *phar_ext_list[] = {
+               ".phar.tar.bz2",
+               ".phar.tar.gz",
+               ".phar.php",
+               ".phar.bz2",
+               ".phar.zip",
+               ".phar.tar",
+               ".phar.gz",
+               ".tar.bz2",
+               ".tar.gz",
+               ".phar",
+               ".tar",
+               ".zip"
+       };
+
        if (!ext) {
                if (phar->is_zip) {
 
@@ -2091,9 +2110,6 @@ static zend_object *phar_rename_archive(phar_archive_data **sphar, char *ext, ze
                return NULL;
        }
 
-       if (ext[0] == '.') {
-               ++ext;
-       }
 
        oldpath = estrndup(phar->fname, phar->fname_len);
        if ((oldname = zend_memrchr(phar->fname, '/', phar->fname_len))) {
@@ -2101,10 +2117,41 @@ static zend_object *phar_rename_archive(phar_archive_data **sphar, char *ext, ze
        } else {
                oldname = phar->fname;
        }
-       oldname_len = strlen(oldname);
 
+       oldname_len = strlen(oldname);
+       /* Copy the old name to create base for the new name */
        basename = estrndup(oldname, oldname_len);
-       spprintf(&newname, 0, "%s.%s", strtok(basename, "."), ext);
+
+       phar_ext_list_len = sizeof(phar_ext_list)/sizeof(phar_ext_list[0]);
+       /* Remove possible PHAR extensions */
+       /* phar_ext_list must be in order of longest extension to shortest */
+       for (i=0; i < phar_ext_list_len; i++) {
+               phar_ext_len = strlen(phar_ext_list[i]);
+               if (phar_ext_len && oldname_len > phar_ext_len) {
+                       /* Check if the basename strings ends with the extension */
+                       if (memcmp(phar_ext_list[i], basename + (oldname_len - phar_ext_len), phar_ext_len) == 0) {
+                               ext_pos = basename + (oldname_len - phar_ext_len);
+                               ext_pos[0] = '\0';
+                               break;
+                       }
+               }
+               ext_pos = NULL;
+       }
+
+       /* If no default PHAR extension found remove the last extension */
+       if (!ext_pos) {
+               ext_pos = strrchr(basename, '.');
+               if (ext_pos) {
+                       ext_pos[0] = '\0';
+               }
+       }
+       ext_pos = NULL;
+
+       if (ext[0] == '.') {
+               ++ext;
+       }
+       /* Append extension to the basename */
+       spprintf(&newname, 0, "%s.%s", basename, ext);
        efree(basename);
 
        basepath = estrndup(oldpath, (strlen(oldpath) - oldname_len));
@@ -2321,7 +2368,7 @@ no_copy:
                phar_add_virtual_dirs(phar, newentry.filename, newentry.filename_len);
        } ZEND_HASH_FOREACH_END();
 
-       if ((ret = phar_rename_archive(&phar, ext, 0))) {
+       if ((ret = phar_rename_archive(&phar, ext))) {
                return ret;
        } else {
                if(phar != NULL) {
index be2a0e10360806bc9c03423d560e3585c6f483d9..380f3e381f91d2aa0ff1b4a9d9f59672e6270244 100644 (file)
@@ -12,7 +12,7 @@ $fname = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.zip';
 $phar = new PharData($fname);
 $phar['x'] = 'hi';
 try {
-       $phar->convertToData(Phar::ZIP, Phar::NONE, '.2.phar.zip');
+       $phar->convertToData(Phar::ZIP, Phar::NONE, 'phar.zip');
 } catch (BadMethodCallException $e) {
        echo $e->getMessage(),"\n";
 }
@@ -21,5 +21,5 @@ try {
 --CLEAN--
 <?php unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.zip');?>
 --EXPECTF--
-data phar "%sbug48377.2.phar.zip" has invalid extension 2.phar.zip
-===DONE===
\ No newline at end of file
+data phar "%sbug48377.2.phar.zip" has invalid extension phar.zip
+===DONE===
diff --git a/ext/phar/tests/bug74196.1.2.3.phar.tar.gz b/ext/phar/tests/bug74196.1.2.3.phar.tar.gz
new file mode 100644 (file)
index 0000000..e2ac1e0
Binary files /dev/null and b/ext/phar/tests/bug74196.1.2.3.phar.tar.gz differ
diff --git a/ext/phar/tests/bug74196.phpt b/ext/phar/tests/bug74196.phpt
new file mode 100644 (file)
index 0000000..7a8e923
--- /dev/null
@@ -0,0 +1,23 @@
+--TEST--
+PHP bug #74196: PharData->decompress() does not correctly support dot names
+--SKIPIF--
+<?php if (!extension_loaded("phar")) die("skip"); ?>
+<?php if (!extension_loaded("zlib")) die("skip"); ?>
+--INI--
+phar.require_hash=0
+phar.readonly=0
+--FILE--
+<?php
+$fname = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.1.2.3.phar.tar.gz';
+$decompressed_name = str_replace( ".gz", "",  $fname);
+var_dump(file_exists($fname));
+
+$phar = new Phar($fname);
+$phar->decompress();
+var_dump(file_exists($decompressed_name));
+unlink($decompressed_name);
+
+?>
+--EXPECTF--
+bool(true)
+bool(true)
index b2ef195ea7868673585afc07f12d937af0795612..2d22c70890af599396c019d0a563258215f5d648 100644 (file)
@@ -91,10 +91,10 @@ var_dump($phar->getAlias());
 unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.phar.zip');
 unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.phar.tar');
 unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.phar');
-unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.2.phar.zip');
-unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.2.phar.tar');
+unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.2.2.phar.zip');
+unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.2.2.2.phar.tar');
 unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.2.phar');
-unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.3.phar.zip');
+unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.2.2.2.3.phar.zip');
 unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.3.phar.tar');
 unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.3.phar');
 ?>
index 10e6973254b6c2ce44048fae411b5e1cc8ef64ce..647bb842d78c535c43bbb2e97f06b9d9ae2ac913 100644 (file)
@@ -74,17 +74,19 @@ try {
 } catch(Exception $e) {
        echo $e->getMessage()."\n";
 }
-
 ?>
 ===DONE===
 --CLEAN--
-<?php 
+<?php
+echo dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.phar.gz' . "\n";
+
 unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.phar.gz');
 unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.tar.gz');
 unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.tar');
-unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.2.tar');
+unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.1.2.tar');
 unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.zip');
 unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.1.zip');
+
 ?>
 --EXPECT--
 =================== new PharData() ==================
@@ -115,4 +117,4 @@ string(0) ""
 NULL
 ================= convertToPhar() ====================
 Cannot write out executable phar archive, phar is read-only
-===DONE===
\ No newline at end of file
+===DONE===
index aba2a6417de5542b4acb0948d46ae372d101b424..6a3f2bf2c81e118561cd510e0247bc8d78b0ba55 100644 (file)
@@ -17,7 +17,7 @@ $fname2 = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.tar';
 $fname3 = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.tar';
 copy(dirname(__FILE__) . '/tar/files/links.tar', $fname2);
 $a = new PharData($fname2);
-$b = $a->convertToExecutable(Phar::TAR, Phar::NONE, '.3.phar.tar');
+$b = $a->convertToExecutable(Phar::TAR, Phar::NONE, '.phar.tar');
 unset($a);
 Phar::unlinkArchive($fname2);
 $b['foo/stat.php'] = '<?php
@@ -58,4 +58,4 @@ bool(false)
 dir
 bool(true)
 bool(false)
-===DONE===
\ No newline at end of file
+===DONE===