[php-src] Issue #8828: phar trying to allocate insane memory sizes
| From: | rainerjung | Date: | Sun, 19 Jun 2022 20:17:24 +0000 |
| Subject: | [php-src] Issue #8828: phar trying to allocate insane memory sizes | ||
| Groups: | php.bugs | ||
| Request: | Send a blank email to php-bugs+get-241763@lists.php.net to get a copy of this message | ||
Issue: https://github.com/php/php-src/issues/8828
Author: rainerjung
### Description
Lots of phar unit tests fail, eg. ext/phar/tests/018.phar.phpt.
The error message is
Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate
18446604268229099552 bytes) in /path/to/ext/phar/tests/018.php on line 13
Note that the demanded memory size "18446604268229099552" does not make sense.
I extracted a standalone test case from 018. This test case runs for PHP 8.1, but not for
8.2.0alpha1. It uses twi scripts:
- x1.php creates x.phar.php. It is based on 018.phpt plus inlined
ext/phar/tests/files/phar_test.inc. Running it produces binary identical files for PHP 8.1 and 8.2.
- x2.php includes x.phar.php and then reports on its contents. This works for 8.1, but fails with
the above error already when just including x.phar.php.
Contents of x1.php:
```php
<?php
$fname = 'x.phar.php';
$pname = 'phar://' . $fname;
$file = "<?php
Phar::mapPhar('hio');
__HALT_COMPILER(); ?>";
$files = array();
$files['a'] = 'a';
$files['b/a'] = 'b';
date_default_timezone_set('UTC');
$manifest = (binary)'';
$gflags = 0;
foreach($files as $name => $cont)
{
global $gflags, $files;
$comp = NULL;
$crc32= NULL;
$clen = NULL;
$ulen = NULL;
$time = isset($ftime) ? $ftime : @mktime(12, 0, 0, 3, 1, 2006);
$flags= 0;
$perm = 0x000001B6;
$meta = NULL;
// overwrite if array
if (is_array($cont))
{
foreach(array('comp','crc32','clen','ulen','time','flags','perm','meta','cont')
as $what)
{
if (isset($cont[$what]))
{
$$what = $cont[$what];
}
}
}
// create if not yet done
if (empty($comp)) $comp = $cont;
if (empty($ulen)) $ulen = strlen($cont);
if (empty($clen)) $clen = strlen($comp);
if (empty($crc32))$crc32= crc32((binary)$cont);
$meta = isset($meta) ? serialize($meta) : "";
// write manifest entry
$manifest .= pack('V', strlen($name)) . (binary)$name;
$manifest .= pack('VVVVVV', $ulen, $time, $clen, $crc32, $flags|$perm, strlen($meta))
. (binary)$meta;
// globals
$gflags |= $flags;
$files[$name] = $comp;
}
if (!isset($alias)) $alias = 'hio';
if (isset($pmeta)) $pmeta = serialize($pmeta); else $pmeta = '';
$manifest = pack('VnVV', count($files), isset($hasdir) ? 0x1110 : 0x1000, $gflags,
strlen($alias)) . (binary)$alias . pack('V', strlen($pmeta)) . (binary)$pmeta . $manifest;
$file = (binary)$file;
$file .= pack('V', strlen($manifest)) . $manifest;
foreach($files as $cont)
{
$file .= (binary)$cont;
}
file_put_contents($fname, $file);
if (@$gzip) {
$fp = gzopen($fname, 'w');
fwrite($fp, $file);
fclose($fp);
}
if (@$bz2) {
$fp = bzopen($fname, 'w');
fwrite($fp, $file);
fclose($fp);
}
?>
```
Contents of x2.php:
```php
<?php
include 'x.phar.php';
$dir = opendir('phar://hio/');
while (false !== ($a = readdir($dir))) {
var_dump($a);
var_dump(is_dir('phar://hio/' . $a));
}
?>
```
Resulted in this output:
```
Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate
18446604268229099552 bytes) in /path/to/x2.php on line 2
```
But I expected this output instead:
```
string(1) "a"
bool(false)
string(1) "b"
bool(true)
```
### PHP Version
PHP 8.2.0alpha1
### Operating System
Linux RHEL 8