mirror of
https://github.com/php/php-src.git
synced 2024-11-24 10:24:11 +08:00
Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4: Fix #77565: Incorrect locator detection in ZIP-based phars
This commit is contained in:
commit
66a74f2f4a
2
NEWS
2
NEWS
@ -39,6 +39,8 @@ PHP NEWS
|
||||
- Phar:
|
||||
. Fixed bug #76929 (zip-based phar does not respect phar.require_hash).
|
||||
(david at bamsoftware, cmb)
|
||||
. Fixed bug #77565 (Incorrect locator detection in ZIP-based phars). (cmb)
|
||||
|
||||
|
||||
07 Jan 2021, PHP 8.0.1
|
||||
|
||||
|
@ -12,7 +12,7 @@ $r = new Phar($fname, 0);
|
||||
}
|
||||
?>
|
||||
--EXPECTF--
|
||||
UnexpectedValueException: phar error: corrupted central directory entry, no magic signature in zip-based phar "%sbug69441.phar" in %sbug69441.php:%d
|
||||
UnexpectedValueException: phar error: end of central directory not found in zip-based phar "%sbug69441.phar" in %sbug69441.php:%d
|
||||
Stack trace:
|
||||
#0 %s%ebug69441.php(%d): Phar->__construct('%s', 0)
|
||||
#1 {main}
|
||||
|
13
ext/phar/tests/bug77565.phpt
Normal file
13
ext/phar/tests/bug77565.phpt
Normal file
@ -0,0 +1,13 @@
|
||||
--TEST--
|
||||
Bug #77565 (Incorrect locator detection in ZIP-based phars)
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (!extension_loaded('phar')) die('skip phar extension not available');
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
$phar = new PharData(__DIR__ . '/bug77565.zip');
|
||||
var_dump($phar['1.zip']->getFilename());
|
||||
?>
|
||||
--EXPECT--
|
||||
string(5) "1.zip"
|
BIN
ext/phar/tests/bug77565.zip
Normal file
BIN
ext/phar/tests/bug77565.zip
Normal file
Binary file not shown.
@ -11,4 +11,4 @@ try {
|
||||
}
|
||||
?>
|
||||
--EXPECTF--
|
||||
phar error: corrupt zip archive, zip file comment truncated in zip-based phar "%sfilecomment.zip"
|
||||
phar error: end of central directory not found in zip-based phar "%sfilecomment.zip"
|
||||
|
105
ext/phar/zip.c
105
ext/phar/zip.c
@ -161,6 +161,29 @@ static void phar_zip_u2d_time(time_t time, char *dtime, char *ddate) /* {{{ */
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static char *phar_find_eocd(const char *s, size_t n)
|
||||
{
|
||||
const char *end = s + n + sizeof("PK\5\6") - 1 - sizeof(phar_zip_dir_end);
|
||||
|
||||
/* search backwards for end of central directory signatures */
|
||||
do {
|
||||
uint16_t comment_len;
|
||||
const char *eocd_start = zend_memnrstr(s, "PK\5\6", sizeof("PK\5\6") - 1, end);
|
||||
|
||||
if (eocd_start == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
ZEND_ASSERT(eocd_start + sizeof(phar_zip_dir_end) <= s + n);
|
||||
comment_len = PHAR_GET_16(((phar_zip_dir_end *) eocd_start)->comment_len);
|
||||
if (eocd_start + sizeof(phar_zip_dir_end) + comment_len == s + n) {
|
||||
/* we can't be sure, but this looks like the proper EOCD signature */
|
||||
return (char *) eocd_start;
|
||||
}
|
||||
end = eocd_start;
|
||||
} while (end > s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does not check for a previously opened phar in the cache.
|
||||
*
|
||||
@ -205,50 +228,48 @@ int phar_parse_zipfile(php_stream *fp, char *fname, size_t fname_len, char *alia
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
while ((p=(char *) memchr(p + 1, 'P', (size_t) (size - (p + 1 - buf)))) != NULL) {
|
||||
if ((p - buf) + sizeof(locator) <= (size_t)size && !memcmp(p + 1, "K\5\6", 3)) {
|
||||
memcpy((void *)&locator, (void *) p, sizeof(locator));
|
||||
if (PHAR_GET_16(locator.centraldisk) != 0 || PHAR_GET_16(locator.disknumber) != 0) {
|
||||
/* split archives not handled */
|
||||
php_stream_close(fp);
|
||||
if (error) {
|
||||
spprintf(error, 4096, "phar error: split archives spanning multiple zips cannot be processed in zip-based phar \"%s\"", fname);
|
||||
}
|
||||
return FAILURE;
|
||||
if ((p = phar_find_eocd(buf, size)) != NULL) {
|
||||
memcpy((void *)&locator, (void *) p, sizeof(locator));
|
||||
if (PHAR_GET_16(locator.centraldisk) != 0 || PHAR_GET_16(locator.disknumber) != 0) {
|
||||
/* split archives not handled */
|
||||
php_stream_close(fp);
|
||||
if (error) {
|
||||
spprintf(error, 4096, "phar error: split archives spanning multiple zips cannot be processed in zip-based phar \"%s\"", fname);
|
||||
}
|
||||
|
||||
if (PHAR_GET_16(locator.counthere) != PHAR_GET_16(locator.count)) {
|
||||
if (error) {
|
||||
spprintf(error, 4096, "phar error: corrupt zip archive, conflicting file count in end of central directory record in zip-based phar \"%s\"", fname);
|
||||
}
|
||||
php_stream_close(fp);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
mydata = pecalloc(1, sizeof(phar_archive_data), PHAR_G(persist));
|
||||
mydata->is_persistent = PHAR_G(persist);
|
||||
|
||||
/* read in archive comment, if any */
|
||||
if (PHAR_GET_16(locator.comment_len)) {
|
||||
|
||||
metadata = p + sizeof(locator);
|
||||
|
||||
if (PHAR_GET_16(locator.comment_len) != size - (metadata - buf)) {
|
||||
if (error) {
|
||||
spprintf(error, 4096, "phar error: corrupt zip archive, zip file comment truncated in zip-based phar \"%s\"", fname);
|
||||
}
|
||||
php_stream_close(fp);
|
||||
pefree(mydata, mydata->is_persistent);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
phar_parse_metadata_lazy(metadata, &mydata->metadata_tracker, PHAR_GET_16(locator.comment_len), mydata->is_persistent);
|
||||
} else {
|
||||
ZVAL_UNDEF(&mydata->metadata_tracker.val);
|
||||
}
|
||||
|
||||
goto foundit;
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
if (PHAR_GET_16(locator.counthere) != PHAR_GET_16(locator.count)) {
|
||||
if (error) {
|
||||
spprintf(error, 4096, "phar error: corrupt zip archive, conflicting file count in end of central directory record in zip-based phar \"%s\"", fname);
|
||||
}
|
||||
php_stream_close(fp);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
mydata = pecalloc(1, sizeof(phar_archive_data), PHAR_G(persist));
|
||||
mydata->is_persistent = PHAR_G(persist);
|
||||
|
||||
/* read in archive comment, if any */
|
||||
if (PHAR_GET_16(locator.comment_len)) {
|
||||
|
||||
metadata = p + sizeof(locator);
|
||||
|
||||
if (PHAR_GET_16(locator.comment_len) != size - (metadata - buf)) {
|
||||
if (error) {
|
||||
spprintf(error, 4096, "phar error: corrupt zip archive, zip file comment truncated in zip-based phar \"%s\"", fname);
|
||||
}
|
||||
php_stream_close(fp);
|
||||
pefree(mydata, mydata->is_persistent);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
phar_parse_metadata_lazy(metadata, &mydata->metadata_tracker, PHAR_GET_16(locator.comment_len), mydata->is_persistent);
|
||||
} else {
|
||||
ZVAL_UNDEF(&mydata->metadata_tracker.val);
|
||||
}
|
||||
|
||||
goto foundit;
|
||||
}
|
||||
|
||||
php_stream_close(fp);
|
||||
|
Loading…
Reference in New Issue
Block a user