]> granicus.if.org Git - php/commitdiff
Fix Bug #49020: phar misinterprets ustar long filename standard
authorGreg Beaver <cellog@php.net>
Wed, 22 Jul 2009 19:51:37 +0000 (19:51 +0000)
committerGreg Beaver <cellog@php.net>
Wed, 22 Jul 2009 19:51:37 +0000 (19:51 +0000)
NEWS
ext/phar/tar.c
ext/phar/tests/tar/bignames.phpt
ext/phar/tests/tar/bignames_overflow.phpt

diff --git a/NEWS b/NEWS
index 531c622bfc3c57c725624207113eb1739b36a36c..902ad8efa07fcf66c8f0f9b2cbd73afd0ba469f9 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -6,6 +6,8 @@ PHP                                                                        NEWS
 - Fixed open_basedir circumvention for mail.log. (Maksymilian Arciemowicz,
   Stas)
 
+- Fixed bug #49020 (phar misinterprets ustar long filename standard).
+  (Greg)
 - Fixed bug #49018 (phar tar stores long filenames wit prefix/name reversed).
   (Greg)
 - Fixed bug #48962 (cURL does not upload files with specified filename).
index 1cd0711cdad4d17de54f178e419c0ff186af1fed..f49907e0be56c7da48f39531835fc865ee730780 100644 (file)
@@ -341,6 +341,7 @@ bail:
                                        break;
                                }
                        }
+                       name[i++] = '/';
                        for (j = 0; j < 100; j++) {
                                name[i+j] = hdr->name[j];
                                if (name[i+j] == '\0') {
@@ -641,14 +642,25 @@ static int phar_tar_writeheaders(void *pDest, void *argument TSRMLS_DC) /* {{{ *
        memset((char *) &header, 0, sizeof(header));
 
        if (entry->filename_len > 100) {
-               if (entry->filename_len > 255) {
+               char *boundary;
+               if (entry->filename_len > 256) {
                        if (fp->error) {
                                spprintf(fp->error, 4096, "tar-based phar \"%s\" cannot be created, filename \"%s\" is too long for tar file format", entry->phar->fname, entry->filename);
                        }
                        return ZEND_HASH_APPLY_STOP;
                }
-               memcpy(header.prefix, entry->filename, entry->filename_len - 100);
-               memcpy(header.name, entry->filename + (entry->filename_len - 100), 100);
+               boundary = entry->filename + entry->filename_len - 101;
+               while (*boundary && *boundary != '/') {
+                       ++boundary;
+               }
+               if (!*boundary || ((boundary - entry->filename) > 155)) {
+                       if (fp->error) {
+                               spprintf(fp->error, 4096, "tar-based phar \"%s\" cannot be created, filename \"%s\" is too long for tar file format", entry->phar->fname, entry->filename);
+                       }
+                       return ZEND_HASH_APPLY_STOP;
+               }
+               memcpy(header.prefix, entry->filename, boundary - entry->filename);
+               memcpy(header.name, boundary + 1, entry->filename_len - (boundary + 1 - entry->filename));
        } else {
                memcpy(header.name, entry->filename, entry->filename_len);
        }
index c6b6bccdb1c3d01d1d9f22cd518fb382f712da45..c10b1cea2f3bb55c44425eb75352df704f497d89 100644 (file)
@@ -8,30 +8,50 @@ phar.require_hash=0
 <?php
 $fname = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.tar';
 $fname2 = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.2.tar';
+$fname3 = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.3.tar';
+$fname4 = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.4.tar';
 $pname = 'phar://' . $fname;
 
 $p1 = new PharData($fname);
-$p1[str_repeat('a', 100) . 'b'] = 'hi';
-$p1[str_repeat('a', 255)] = 'hi2';
+$p1[str_repeat('a', 100) . '/b'] = 'hi';
+$p1[str_repeat('a', 155) . '/' . str_repeat('b', 100)] = 'hi2';
 copy($fname, $fname2);
 $p2 = new PharData($fname2);
-echo $p2[str_repeat('a', 100) . 'b']->getContent() . "\n";
-echo $p2[str_repeat('a', 255)]->getContent() . "\n";
+echo $p2[str_repeat('a', 100) . '/b']->getContent() . "\n";
+echo $p2[str_repeat('a', 155) . '/' . str_repeat('b', 100)]->getContent() . "\n";
 
 try {
        $p2[str_repeat('a', 400)] = 'yuck';
 } catch (Exception $e) {
        echo $e->getMessage() . "\n";
 }
+
+try {
+       $p2 = new PharData($fname3);
+       $p2[str_repeat('a', 101)] = 'yuck';
+} catch (Exception $e) {
+       echo $e->getMessage() . "\n";
+}
+
+try {
+       $p2 = new PharData($fname4);
+       $p2[str_repeat('b', 160) . '/' . str_repeat('a', 90)] = 'yuck';
+} catch (Exception $e) {
+       echo $e->getMessage() . "\n";
+}
 ?>
 ===DONE===
 --CLEAN--
 <?php
 unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.tar');
 unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.2.tar');
+@unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.3.tar');
+@unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.4.tar');
 ?>
 --EXPECTF--
 hi
 hi2
 tar-based phar "%sbignames.2.tar" cannot be created, filename "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" is too long for tar file format
+tar-based phar "%sbignames.3.tar" cannot be created, filename "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" is too long for tar file format
+tar-based phar "%sbignames.4.tar" cannot be created, filename "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" is too long for tar file format
 ===DONE===
index 80873119f6ca1791dee520fac7f77cd5ad3e11ae..359e9c63417dc6f14b7336d384a6cb288abcf0e2 100644 (file)
@@ -22,8 +22,8 @@ $p1 = new PharData($fname);
 foreach ($p1 as $file) {
        echo $file->getFileName(), "\n";
 }
-echo $p1[str_repeat('a', 101)]->getContent() . "\n";
-echo $p1[str_repeat('a', 255)]->getContent() . "\n";
+echo $p1['a/' . str_repeat('a', 100)]->getContent() . "\n";
+echo $p1[str_repeat('a', 155) . '/' . str_repeat('a', 100)]->getContent() . "\n";
 
 ?>
 ===DONE===
@@ -33,8 +33,8 @@ unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.tar');
 unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.2.tar');
 ?>
 --EXPECT--
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+a
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 hi
 hi2
 ===DONE===