Skip to content

Commit 93d7df0

Browse files
gh-149945: Fix potential OOM for gzip with large header
Do not read the whole filename and comment to memory for calculating the CRC.
1 parent 18281db commit 93d7df0

1 file changed

Lines changed: 30 additions & 20 deletions

File tree

Lib/gzip.py

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -484,14 +484,22 @@ def _read_exact(fp, n):
484484
return data
485485

486486

487-
def _read_until_null(fp, append_to):
487+
def _read_until_null(fp, crc=None):
488488
'''Read until the first encountered null byte in fp.
489-
Append to given byte array object'''
490-
while True:
491-
s = fp.read(1)
492-
append_to += s
493-
if not s or s == b'\000':
494-
break
489+
If crc is not None, update and return the CRC.
490+
'''
491+
if crc is None:
492+
while True:
493+
s = fp.read(1)
494+
if not s or s == b'\000':
495+
break
496+
else:
497+
while True:
498+
s = fp.read(1)
499+
crc = zlib.crc32(s, crc)
500+
if not s or s == b'\000':
501+
break
502+
return crc
495503

496504

497505
def _read_gzip_header(fp):
@@ -517,30 +525,32 @@ def _read_gzip_header(fp):
517525
return last_mtime
518526
if flag == FNAME:
519527
# Read and discard a null-terminated string containing the filename
520-
while True:
521-
s = fp.read(1)
522-
if not s or s==b'\000':
523-
break
528+
_read_until_null(fp)
524529
return last_mtime
525530

526531
# Processing for more complex flags. Save header parts for FHCRC checking.
527-
header = bytearray(magic + base_header)
532+
if flag & FHCRC:
533+
crc = zlib.crc32(magic + base_header)
534+
else:
535+
crc = None
528536
if flag & FEXTRA:
529537
extra_len_bytes = _read_exact(fp, 2)
530538
extra_len, = struct.unpack("<H", extra_len_bytes)
531-
header += extra_len_bytes
532-
header += _read_exact(fp, extra_len)
539+
extra = _read_exact(fp, extra_len)
540+
if crc is not None:
541+
crc = zlib.crc32(extra_len_bytes, crc)
542+
crc = zlib.crc32(extra, crc)
533543
if flag & FNAME:
534-
_read_until_null(fp, append_to=header)
544+
crc = _read_until_null(fp, crc)
535545
if flag & FCOMMENT:
536-
_read_until_null(fp, append_to=header)
537-
if flag & FHCRC:
546+
crc = _read_until_null(fp, crc)
547+
if crc is not None:
538548
# Header CRC is the last 16 bits of a crc32.
539549
header_crc, = struct.unpack("<H", _read_exact(fp, 2))
540-
true_crc = zlib.crc32(header) & 0xFFFF
541-
if header_crc != true_crc:
550+
crc = crc & 0xFFFF
551+
if header_crc != crc:
542552
raise BadGzipFile(f"Corrupted gzip header. Checksums do not "
543-
f"match: {true_crc:04x} != {header_crc:04x}")
553+
f"match: {crc:04x} != {header_crc:04x}")
544554
return last_mtime
545555

546556

0 commit comments

Comments
 (0)