From 667c59abd697d5d80cb0cadf6a5cb7d94dee3a22 Mon Sep 17 00:00:00 2001 From: Greg Beaver Date: Wed, 22 Jul 2009 19:51:37 +0000 Subject: [PATCH] Fix Bug #49020: phar misinterprets ustar long filename standard --- NEWS | 2 ++ ext/phar/tar.c | 18 ++++++++++++--- ext/phar/tests/tar/bignames.phpt | 28 +++++++++++++++++++---- ext/phar/tests/tar/bignames_overflow.phpt | 8 +++---- 4 files changed, 45 insertions(+), 11 deletions(-) diff --git a/NEWS b/NEWS index 531c622bfc3..902ad8efa07 100644 --- 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). diff --git a/ext/phar/tar.c b/ext/phar/tar.c index 1cd0711cdad..f49907e0be5 100644 --- a/ext/phar/tar.c +++ b/ext/phar/tar.c @@ -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); } diff --git a/ext/phar/tests/tar/bignames.phpt b/ext/phar/tests/tar/bignames.phpt index c6b6bccdb1c..c10b1cea2f3 100644 --- a/ext/phar/tests/tar/bignames.phpt +++ b/ext/phar/tests/tar/bignames.phpt @@ -8,30 +8,50 @@ phar.require_hash=0 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-- --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=== diff --git a/ext/phar/tests/tar/bignames_overflow.phpt b/ext/phar/tests/tar/bignames_overflow.phpt index 80873119f6c..359e9c63417 100644 --- a/ext/phar/tests/tar/bignames_overflow.phpt +++ b/ext/phar/tests/tar/bignames_overflow.phpt @@ -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===