Skip to content

Fixed GH-21376: gzfile and readgzfile no longer detect corrupted gzip…#21381

Open
GabrielCordeiroBarrosoTeles wants to merge 2 commits intophp:PHP-8.5from
GabrielCordeiroBarrosoTeles:fix-21376-gzfile-corrupt-gzip
Open

Fixed GH-21376: gzfile and readgzfile no longer detect corrupted gzip…#21381
GabrielCordeiroBarrosoTeles wants to merge 2 commits intophp:PHP-8.5from
GabrielCordeiroBarrosoTeles:fix-21376-gzfile-corrupt-gzip

Conversation

@GabrielCordeiroBarrosoTeles
Copy link

@GabrielCordeiroBarrosoTeles GabrielCordeiroBarrosoTeles commented Mar 7, 2026

Fixes #21376

Summary

From PHP 8.5.3, gzfile() and readgzfile() no longer treat corrupted gzip data as an error. They may return decompressed data (garbage) instead of an empty array and -1 respectively, as in previous versions.

This change restores the previous behaviour when the zlib stream reports a data or stream error.

Changes

  1. ext/zlib/zlib_fopen_wrapper.c
    After each gzread() call (including when it returns 0), the wrapper now checks gzerror(). If the error is Z_DATA_ERROR or Z_STREAM_ERROR, the read is treated as failed (return -1), so callers receive error semantics instead of invalid data. Checking when read >= 0 covers Windows, where zlib may return 0 bytes while setting the error.

  2. ext/zlib/zlib.c
    readgzfile() now stores the return value of php_stream_passthru() in an ssize_t and returns it with RETURN_LONG((zend_long) size), so a stream error (-1) is returned to PHP as -1 instead of being converted to a large positive value when stored in a size_t.
    When passthru() returns 0, a one-byte read is performed; if that read fails (returns < 0), the function returns -1. This fallback fixes corrupt gzip handling on Windows where gzerror() may not be set when gzread() returns 0.

  3. ext/zlib/tests/bug21376_corrupt_gz.phpt
    New test that uses a minimal invalid gzip file and asserts that gzfile() returns an empty array and readgzfile() returns -1.

  4. NEWS
    Entry added for this fix under the Zlib section.

Testing

The new regression test was run locally (see screenshot below).

What the screenshot shows: Output of run-tests.php ext/zlib/tests/bug21376_corrupt_gz.phpt inside Docker (Ubuntu 24.04). One test is executed — the one that checks corrupted gzip handling — and it PASSes. The summary at the bottom reports: 1 test, 1 passed, 0 failed.

Captura de Tela 2026-03-07 às 18 34 00

…zip 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.
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 (phpGH-21376).
@GabrielCordeiroBarrosoTeles GabrielCordeiroBarrosoTeles force-pushed the fix-21376-gzfile-corrupt-gzip branch from aa61385 to 7e33691 Compare March 8, 2026 01:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant