mirror of
https://github.com/php/php-src.git
synced 2026-03-24 00:02:20 +01:00
Fix GH-16695: phar:// tar parser and zero-length file header blocks
There are two issues: 1) There's an off-by-one in the check for the minimum file size for a tar (i.e. `>` instead of `>=`). 2) The loop in the tar parsing parses a header, and then unconditionally reads the next one. However, that doesn't necessarily exist. Instead, we remove the loop condition and check for the end of the file before reading the next header. Note that we can't use php_stream_eof as the flag may not be set yet when we're already at the end. Closes GH-16700.
This commit is contained in:
4
NEWS
4
NEWS
@@ -19,6 +19,10 @@ PHP NEWS
|
||||
- PDO:
|
||||
. Fixed memory leak of `setFetchMode()`. (SakiTakamachi)
|
||||
|
||||
- Phar:
|
||||
. Fixed bug GH-16695 (phar:// tar parser and zero-length file header blocks).
|
||||
(nielsdos)
|
||||
|
||||
21 Nov 2024, PHP 8.2.26
|
||||
|
||||
- Cli:
|
||||
|
||||
@@ -1774,7 +1774,7 @@ static int phar_open_from_fp(php_stream* fp, char *fname, size_t fname_len, char
|
||||
return phar_parse_zipfile(fp, fname, fname_len, alias, alias_len, pphar, error);
|
||||
}
|
||||
|
||||
if (got > 512) {
|
||||
if (got >= 512) {
|
||||
if (phar_is_tar(pos, fname)) {
|
||||
php_stream_rewind(fp);
|
||||
return phar_parse_tarfile(fp, fname, fname_len, alias, alias_len, pphar, is_data, compression, error);
|
||||
|
||||
@@ -254,9 +254,8 @@ int phar_parse_tarfile(php_stream* fp, char *fname, size_t fname_len, char *alia
|
||||
entry.is_tar = 1;
|
||||
entry.is_crc_checked = 1;
|
||||
entry.phar = myphar;
|
||||
pos += sizeof(buf);
|
||||
|
||||
do {
|
||||
while (true) {
|
||||
phar_entry_info *newentry;
|
||||
|
||||
pos = php_stream_tell(fp);
|
||||
@@ -597,6 +596,11 @@ next:
|
||||
}
|
||||
}
|
||||
|
||||
/* Only read next header if we're not yet at the end */
|
||||
if (php_stream_tell(fp) == totalsize) {
|
||||
break;
|
||||
}
|
||||
|
||||
read = php_stream_read(fp, buf, sizeof(buf));
|
||||
|
||||
if (read != sizeof(buf)) {
|
||||
@@ -607,7 +611,7 @@ next:
|
||||
phar_destroy_phar_data(myphar);
|
||||
return FAILURE;
|
||||
}
|
||||
} while (!php_stream_eof(fp));
|
||||
}
|
||||
|
||||
if (zend_hash_str_exists(&(myphar->manifest), ".phar/stub.php", sizeof(".phar/stub.php")-1)) {
|
||||
myphar->is_data = 0;
|
||||
|
||||
28
ext/phar/tests/tar/gh16695_1.phpt
Normal file
28
ext/phar/tests/tar/gh16695_1.phpt
Normal file
@@ -0,0 +1,28 @@
|
||||
--TEST--
|
||||
GH-16695 (phar:// tar parser and zero-length file header blocks)
|
||||
--CREDITS--
|
||||
hakre
|
||||
--EXTENSIONS--
|
||||
phar
|
||||
--INI--
|
||||
phar.require_hash=0
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$reportTar = __DIR__.'/gh16695_1.tmp';
|
||||
|
||||
$length = file_put_contents($reportTar, base64_decode('dGxzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAwMDA3MDAAMDAwMDAwMAAwMDAwMDAwADAwMDAwMDAwMDAwADAwMDAwMDAwMDAwADAwNzcxNgAgNQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB1c3RhcgAwMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwMDAwMDAwADAwMDAwMDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA='));
|
||||
var_dump($length);
|
||||
$buffer = file_get_contents("phar://$reportTar/tls");
|
||||
var_dump($buffer);
|
||||
|
||||
?>
|
||||
--CLEAN--
|
||||
<?php
|
||||
@unlink(__DIR__.'/gh16695_1.tmp');
|
||||
?>
|
||||
--EXPECTF--
|
||||
int(512)
|
||||
|
||||
Warning: file_get_contents(%stls): Failed to open stream: phar error: path "tls" is a directory in %s on line %d
|
||||
bool(false)
|
||||
26
ext/phar/tests/tar/gh16695_2.phpt
Normal file
26
ext/phar/tests/tar/gh16695_2.phpt
Normal file
@@ -0,0 +1,26 @@
|
||||
--TEST--
|
||||
GH-16695 (phar:// tar parser and zero-length file header blocks)
|
||||
--CREDITS--
|
||||
hakre
|
||||
--EXTENSIONS--
|
||||
phar
|
||||
--INI--
|
||||
phar.require_hash=0
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$reportTar = __DIR__.'/gh16695_2.tmp';
|
||||
|
||||
$length = file_put_contents($reportTar, base64_decode('bWV0YS5qc29uAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAwMDA2NDQAMDAwMDAwMAAwMDAwMDAwADAwMDAwMDAwMTcyADAwMDAwMDAwMDAwADAxMTAyNgAgMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB1c3RhcgAwMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwMDAwMDAwADAwMDAwMDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB7Ik5hbWUiOiJkZWZhdWx0IiwiTWV0YWRhdGEiOnt9LCJFbmRwb2ludHMiOnsiZG9ja2VyIjp7Ikhvc3QiOiJ1bml4Oi8vL3J1bi91c2VyLzEwMDAvZG9ja2VyLnNvY2siLCJTa2lwVExTVmVyaWZ5IjpmYWxzZX19fQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=='));
|
||||
var_dump($length);
|
||||
$buffer = file_get_contents("phar://$reportTar/meta.json");
|
||||
var_dump($buffer);
|
||||
|
||||
?>
|
||||
--CLEAN--
|
||||
<?php
|
||||
@unlink(__DIR__.'/gh16695_2.tmp');
|
||||
?>
|
||||
--EXPECT--
|
||||
int(1024)
|
||||
string(122) "{"Name":"default","Metadata":{},"Endpoints":{"docker":{"Host":"unix:///run/user/1000/docker.sock","SkipTLSVerify":false}}}"
|
||||
26
ext/phar/tests/tar/gh16695_3.phpt
Normal file
26
ext/phar/tests/tar/gh16695_3.phpt
Normal file
@@ -0,0 +1,26 @@
|
||||
--TEST--
|
||||
GH-16695 (phar:// tar parser and zero-length file header blocks)
|
||||
--CREDITS--
|
||||
hakre
|
||||
--EXTENSIONS--
|
||||
phar
|
||||
--INI--
|
||||
phar.require_hash=0
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$reportTar = __DIR__.'/gh16695_3.tmp';
|
||||
|
||||
$length = file_put_contents($reportTar, base64_decode('dGxzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAwMDA3MDAAMDAwMDAwMAAwMDAwMDAwADAwMDAwMDAwMDAwADAwMDAwMDAwMDAwADAwNzcxMQAgMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB1c3RhcgAwMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwMDAwMDAwADAwMDAwMDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA='));
|
||||
var_dump($length);
|
||||
$buffer = file_get_contents("phar://$reportTar/tls");
|
||||
var_dump($buffer);
|
||||
|
||||
?>
|
||||
--CLEAN--
|
||||
<?php
|
||||
@unlink(__DIR__.'/gh16695_3.tmp');
|
||||
?>
|
||||
--EXPECT--
|
||||
int(512)
|
||||
string(0) ""
|
||||
Reference in New Issue
Block a user