Skip to content

Commit 7e33691

Browse files
Fix readgzfile() on Windows: check gzerror when gzread returns 0
On Windows, zlib may return 0 bytes for corrupted gzip while setting Z_DATA_ERROR. Check gzerror() for read >= 0 so that case is treated as failure and readgzfile() returns -1 (GH-21376).
1 parent 48028bc commit 7e33691

File tree

2 files changed

+15
-2
lines changed

2 files changed

+15
-2
lines changed

ext/zlib/zlib.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "php_ini.h"
2828
#include "ext/standard/info.h"
2929
#include "ext/standard/file.h"
30+
#include "Zend/zend_virtual_cwd.h"
3031
#include "php_zlib.h"
3132
#include "zlib_arginfo.h"
3233

@@ -694,6 +695,18 @@ PHP_FUNCTION(readgzfile)
694695
RETURN_FALSE;
695696
}
696697
size = php_stream_passthru(stream);
698+
/* On Windows, corrupt gzip may yield 0 from passthru; stream eof is already set so a further read returns 0 (not -1). Treat 0 bytes read from a non-empty file as error. */
699+
if (size == 0) {
700+
char buf[1];
701+
if (php_stream_read(stream, buf, 1) < 0) {
702+
size = -1;
703+
} else {
704+
zend_stat_t st = {0};
705+
if (VCWD_STAT(filename, &st) == 0 && st.st_size > 0) {
706+
size = -1;
707+
}
708+
}
709+
}
697710
php_stream_close(stream);
698711
RETURN_LONG((zend_long) size);
699712
}

ext/zlib/zlib_fopen_wrapper.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,8 @@ 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) {
68+
/* Corrupt gzip data: gzread() may return 0 or bytes while gzerror indicates Z_DATA_ERROR (e.g. on Windows) */
69+
if (read >= 0) {
7070
int zerr;
7171
gzerror(self->gz_file, &zerr);
7272
if (zerr == Z_DATA_ERROR || zerr == Z_STREAM_ERROR) {

0 commit comments

Comments
 (0)