Skip to content

Commit 48028bc

Browse files
Gabriel CordeiroGabriel Cordeiro
authored andcommitted
Fixed GH-21376: gzfile and readgzfile no longer detect corrupted gzip data
When gzip data is corrupted, gzread() can return positive byte count while gzerror() indicates Z_DATA_ERROR. The zlib stream wrapper now checks gzerror() after each gzread() and returns -1 so that gzfile() returns an empty array and readgzfile() returns -1 as in previous PHP versions. readgzfile() also now uses ssize_t for php_stream_passthru() result so that -1 is correctly returned on error instead of being cast to a large size_t.
1 parent 10e02b0 commit 48028bc

4 files changed

Lines changed: 41 additions & 2 deletions

File tree

NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,10 @@ PHP NEWS
320320
. Fixed bug GH-20439 (xml_set_default_handler() does not properly handle
321321
special characters in attributes when passing data to callback). (ndossche)
322322

323+
- Zlib:
324+
. Fixed bug GH-21376 (gzfile and readgzfile no longer detect corrupted gzip
325+
data). (GabrielCordeiroBarrosoTeles)
326+
323327
- Zip:
324328
. Fix crash in property existence test. (ndossche)
325329
. Don't truncate return value of zip_fread() with user sizes. (ndossche)
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
--TEST--
2+
Bug #21376: gzfile and readgzfile must detect corrupted gzip data
3+
--EXTENSIONS--
4+
zlib
5+
--FILE--
6+
<?php
7+
/* Minimal invalid gzip: magic + garbage so zlib reports Z_DATA_ERROR */
8+
$corrupt = __DIR__ . '/bug21376_corrupt.gz';
9+
file_put_contents($corrupt, "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x03" . "invalid compressed data");
10+
11+
$result = @gzfile($corrupt);
12+
var_dump($result);
13+
14+
ob_start();
15+
$result = @readgzfile($corrupt);
16+
ob_end_clean();
17+
var_dump($result);
18+
19+
@unlink($corrupt);
20+
?>
21+
--EXPECT--
22+
array(0) {
23+
}
24+
int(-1)

ext/zlib/zlib.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -677,7 +677,7 @@ PHP_FUNCTION(readgzfile)
677677
size_t filename_len;
678678
int flags = REPORT_ERRORS;
679679
php_stream *stream;
680-
size_t size;
680+
ssize_t size;
681681
bool use_include_path = false;
682682

683683
if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|b", &filename, &filename_len, &use_include_path) == FAILURE) {
@@ -695,7 +695,7 @@ PHP_FUNCTION(readgzfile)
695695
}
696696
size = php_stream_passthru(stream);
697697
php_stream_close(stream);
698-
RETURN_LONG(size);
698+
RETURN_LONG((zend_long) size);
699699
}
700700
/* }}} */
701701

ext/zlib/zlib_fopen_wrapper.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,17 @@ static ssize_t php_gziop_read(php_stream *stream, char *buf, size_t count)
6565
return read;
6666
}
6767

68+
/* Corrupt gzip data: gzread() may return bytes while gzerror indicates Z_DATA_ERROR */
69+
if (read > 0) {
70+
int zerr;
71+
gzerror(self->gz_file, &zerr);
72+
if (zerr == Z_DATA_ERROR || zerr == Z_STREAM_ERROR) {
73+
stream->eof = 1;
74+
php_gziop_report_errors(stream, chunk_size, "Read");
75+
return -1;
76+
}
77+
}
78+
6879
total_read += read;
6980
buf += read;
7081
} while (count > 0 && !stream->eof);

0 commit comments

Comments
 (0)