Fix GH-13833: Applying zero offset to null pointer in zend_hash.c

MAPPHAR_FAIL will call the destructor of the manifest, mounted_dirs, and
virtual_dirs tables. When a new phar object is allocated using (p)ecalloc,
the bytes are zeroed, but the flag for an uninitialized table is
non-zero. So we have to manually set the flag in case that we have a
code path that can destroy the tables without first initializing them at
least once.

Closes GH-13847.
This commit is contained in:
Niels Dossche 2024-03-31 01:17:49 +01:00
parent ed8ed714a8
commit 47bb6c1b79
No known key found for this signature in database
GPG Key ID: A17A7C526FE17078
4 changed files with 70 additions and 20 deletions

2
NEWS
View File

@ -13,6 +13,8 @@ PHP NEWS
- Phar:
. Fixed bug GH-13836 (Renaming a file in a Phar to an already existing
filename causes a NULL pointer dereference). (nielsdos)
. Fixed bug GH-13833 (Applying zero offset to null pointer in zend_hash.c).
(nielsdos)
- PHPDBG:
. Fixed bug GH-13827 (Null pointer access of type 'zval' in phpdbg_frame).

View File

@ -1090,6 +1090,9 @@ static int phar_parse_pharfile(php_stream *fp, char *fname, size_t fname_len, ch
mydata = pecalloc(1, sizeof(phar_archive_data), PHAR_G(persist));
mydata->is_persistent = PHAR_G(persist);
HT_INVALIDATE(&mydata->manifest);
HT_INVALIDATE(&mydata->mounted_dirs);
HT_INVALIDATE(&mydata->virtual_dirs);
/* check whether we have meta data, zero check works regardless of byte order */
SAFE_PHAR_GET_32(buffer, endbuffer, len);

View File

@ -1,33 +1,45 @@
--TEST--
GH-13836 (Renaming a file in a Phar to an already existing filename causes a NULL pointer dereference)
--EXTENSIONS--
phar
GH-13833 (Applying zero offset to null pointer in zend_hash.c)
--INI--
phar.require_hash=0
phar.readonly=0
--FILE--
<?php
$fname = __DIR__ . '/gh13836.phar';
$fname = __DIR__ . '/gh13833.phar';
$pname = 'phar://' . $fname;
$file = "<?php
Phar::mapPhar('hio');
__HALT_COMPILER(); ?>";
$files = array();
$files['a'] = 'a';
include 'files/phar_test.inc';
include $fname;
$phar = new Phar($fname, 0, 'a.phar');
$phar['x'] = 'hi1';
$phar['y'] = 'hi2';
$file = "<?php __HALT_COMPILER(); ?>";
$files['a'] = array('cont' => 'a');
include 'files/phar_test.inc';
var_dump(rename("phar://a.phar/x", "phar://a.phar/y"));
var_dump(isset($phar['x']));
var_dump($phar['y']);
$phar = new Phar($fname);
$phar->setMetadata((object) ['my' => 'friend']);
// NOTE: Phar will use the cached value of metadata if setMetaData was called on that Phar path before.
// Save the writes to the phar and use a different file path.
$fname_new = "$fname.copy.phar";
copy($fname, $fname_new);
try {
new Phar($fname_new);
} catch (UnexpectedValueException $e) {
echo $e->getMessage(), "\n";
}
?>
--EXTENSIONS--
phar
--CLEAN--
<?php
unlink(__DIR__ . '/gh13836.phar');
unlink(__DIR__ . '/gh13833.phar');
unlink(__DIR__ . '/gh13833.phar.copy.phar');
?>
--CREDITS--
Yuancheng Jiang <yuancheng@comp.nus.edu.sg>
Felix De Vliegher <felix.devliegher@gmail.com>
--EXPECTF--
bool(true)
bool(false)
object(PharFileInfo)#2 (2) {
["pathName":"SplFileInfo":private]=>
string(%d) "phar://%sgh13836.phar/y"
["fileName":"SplFileInfo":private]=>
string(1) "y"
}
internal corruption of phar "%sgh13833.phar.copy.phar" (trying to read past buffer end)

View File

@ -0,0 +1,33 @@
--TEST--
GH-13836 (Renaming a file in a Phar to an already existing filename causes a NULL pointer dereference)
--EXTENSIONS--
phar
--INI--
phar.require_hash=0
phar.readonly=0
--FILE--
<?php
$fname = __DIR__ . '/gh13836.phar';
$phar = new Phar($fname, 0, 'a.phar');
$phar['x'] = 'hi1';
$phar['y'] = 'hi2';
var_dump(rename("phar://a.phar/x", "phar://a.phar/y"));
var_dump(isset($phar['x']));
var_dump($phar['y']);
?>
--CLEAN--
<?php
unlink(__DIR__ . '/gh13836.phar');
?>
--EXPECTF--
bool(true)
bool(false)
object(PharFileInfo)#2 (2) {
["pathName":"SplFileInfo":private]=>
string(%d) "phar://%sgh13836.phar/y"
["fileName":"SplFileInfo":private]=>
string(1) "y"
}