Fixed GH-21376: gzfile and readgzfile no longer detect corrupted gzip…#21381
Open
GabrielCordeiroBarrosoTeles wants to merge 2 commits intophp:PHP-8.5from
Open
Conversation
…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.
22440ad to
aa61385
Compare
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).
aa61385 to
7e33691
Compare
devnexen
reviewed
Mar 9, 2026
| } | ||
| size = php_stream_passthru(stream); | ||
| /* 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. */ | ||
| if (size == 0) { |
Member
There was a problem hiding this comment.
hmmm I do not know that well gz extension however this block does not give me that much confidence (reliability wise). cc @ndossche wdyt ?
There was a problem hiding this comment.
Thanks for the review @devnexen . This block is a workaround for the Windows case where the wrapper returns 0 instead of -1 for corrupt gzip. I'm happy to implement a more direct fix in the wrapper/stream if you think that's a better approach.
Member
There was a problem hiding this comment.
No worries I figured from your comments :) but just asking more knowledgable people which direction is best. Cheers
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #21376
Summary
From PHP 8.5.3,
gzfile()andreadgzfile()no longer treat corrupted gzip data as an error. They may return decompressed data (garbage) instead of an empty array and-1respectively, as in previous versions.This change restores the previous behaviour when the zlib stream reports a data or stream error.
Changes
ext/zlib/zlib_fopen_wrapper.c
After each
gzread()call (including when it returns0), the wrapper now checksgzerror(). If the error isZ_DATA_ERRORorZ_STREAM_ERROR, the read is treated as failed (return-1), so callers receive error semantics instead of invalid data. Checking whenread >= 0covers Windows, where zlib may return 0 bytes while setting the error.ext/zlib/zlib.c
readgzfile()now stores the return value ofphp_stream_passthru()in anssize_tand returns it withRETURN_LONG((zend_long) size), so a stream error (-1) is returned to PHP as-1instead of being converted to a large positive value when stored in asize_t.When
passthru()returns0, a one-byte read is performed; if that read fails (returns< 0), the function returns-1. This fallback fixes corrupt gzip handling on Windows wheregzerror()may not be set whengzread()returns 0.ext/zlib/tests/bug21376_corrupt_gz.phpt
New test that uses a minimal invalid gzip file and asserts that
gzfile()returns an empty array andreadgzfile()returns-1.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.phptinside 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.