From f09c6fedf135543a95ff2111da24b4ec02d2eebd Mon Sep 17 00:00:00 2001 From: Muhammad Haris Awan Date: Wed, 28 Oct 2026 01:44:59 +0500 Subject: [PATCH 1/3] gh-41668: Add partial data recovery support for truncated gzip streams --- Lib/compression/_common/_streams.py | 9 +++++++-- Lib/gzip.py | 11 +++++++++-- Lib/test/test_gzip.py | 11 +++++++++++ ...026-10-28-01-44-00.gh-issue-41668.gzip-partial.rst | 1 + 4 files changed, 28 insertions(+), 4 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-10-28-01-44-00.gh-issue-41668.gzip-partial.rst diff --git a/Lib/compression/_common/_streams.py b/Lib/compression/_common/_streams.py index 9f367d4e30440f..3450d39e741b07 100644 --- a/Lib/compression/_common/_streams.py +++ b/Lib/compression/_common/_streams.py @@ -115,8 +115,13 @@ def readall(self): # sys.maxsize means the max length of output buffer is unlimited, # so that the whole input buffer can be decompressed within one # .decompress() call. - while data := self.read(sys.maxsize): - chunks.append(data) + try: + while data := self.read(sys.maxsize): + chunks.append(data) + except EOFError as exc: + if chunks: + exc.partial_data = b"".join(chunks) + raise return b"".join(chunks) diff --git a/Lib/gzip.py b/Lib/gzip.py index 5b6ebcfef45c3a..b917bc05bed67b 100644 --- a/Lib/gzip.py +++ b/Lib/gzip.py @@ -677,9 +677,10 @@ def compress(data, compresslevel=_COMPRESS_LEVEL_TRADEOFF, *, mtime=0): return header + gzip_data[10:] -def decompress(data): +def decompress(data, *, partial=False): """Decompress a gzip compressed string in one shot. Return the decompressed string. + If partial is True, returns data decompressed prior to an unexpected EOF. """ decompressed_members = [] while True: @@ -691,8 +692,14 @@ def decompress(data): # Read all the data except the header decompressed = do.decompress(data[fp.tell():]) if not do.eof or len(do.unused_data) < 8: - raise EOFError("Compressed file ended before the end-of-stream " + if partial and decompressed: + decompressed_members.append(decompressed) + return b"".join(decompressed_members) + exc = EOFError("Compressed file ended before the end-of-stream " "marker was reached") + if decompressed: + exc.partial_data = decompressed + raise exc crc, length = struct.unpack(" Date: Wed, 28 Oct 2026 23:44:43 +0500 Subject: [PATCH 2/3] gh-41668: Retrigger CI for macOS runner From dc08ea5ade3772cc93690b25d1e87eb91f15b68f Mon Sep 17 00:00:00 2001 From: Muhammad Haris Awan Date: Thu, 29 Oct 2026 04:17:47 +0500 Subject: [PATCH 3/3] gh-41668: Retrigger CI