@@ -426,29 +426,60 @@ def _read_gzip_header(fp):
426
426
427
427
if magic != b'\037 \213 ' :
428
428
raise BadGzipFile ('Not a gzipped file (%r)' % magic )
429
-
430
- (method , flag , last_mtime ) = struct .unpack ("<BBIxx" , _read_exact ( fp , 8 ) )
429
+ base_header = _read_exact ( fp , 8 )
430
+ (method , flag , last_mtime ) = struct .unpack ("<BBIxx" , base_header )
431
431
if method != 8 :
432
432
raise BadGzipFile ('Unknown compression method' )
433
433
434
+ # FHCRC will be checked often. So save the result of the check.
435
+ fhcrc = flag & FHCRC
436
+ # Only create and append to a list of header parts when FHCRC is set.
437
+ # In the most common use cases FHCRC is not set. So we optimize for those
438
+ # cases.
439
+ if fhcrc :
440
+ header_parts = [magic , base_header ]
441
+
434
442
if flag & FEXTRA :
435
- # Read & discard the extra field, if present
436
- extra_len , = struct .unpack ("<H" , _read_exact (fp , 2 ))
437
- _read_exact (fp , extra_len )
443
+ # Read the extra field, if present, save the fields if FHCRC is set.
444
+ extra_len_bytes = _read_exact (fp , 2 )
445
+ extra_len , = struct .unpack ("<H" , extra_len_bytes )
446
+ extra = _read_exact (fp , extra_len )
447
+ if fhcrc :
448
+ header_parts .extend ([extra_len_bytes , extra ])
449
+
438
450
if flag & FNAME :
439
- # Read and discard a null-terminated string containing the filename
451
+ # Read a null-terminated string containing the filename. Save it
452
+ # if FHCRC is set.
440
453
while True :
441
454
s = fp .read (1 )
442
- if not s or s == b'\000 ' :
455
+ if not s :
456
+ raise EOFError ("Compressed file ended before the "
457
+ "end-of-stream marker was reached" )
458
+ if fhcrc :
459
+ header_parts .append (s )
460
+ if s == b'\000 ' :
443
461
break
444
462
if flag & FCOMMENT :
445
- # Read and discard a null-terminated string containing a comment
463
+ # Read a null-terminated string containing the filename. Save it
464
+ # if FHCRC is set.
446
465
while True :
447
466
s = fp .read (1 )
448
- if not s or s == b'\000 ' :
467
+ if not s :
468
+ raise EOFError ("Compressed file ended before the "
469
+ "end-of-stream marker was reached" )
470
+ if fhcrc :
471
+ header_parts .append (s )
472
+ if s == b'\000 ' :
449
473
break
450
- if flag & FHCRC :
451
- _read_exact (fp , 2 ) # Read & discard the 16-bit header CRC
474
+
475
+ if fhcrc :
476
+ # Read the 16-bit header CRC and check it against the header.
477
+ header_crc , = struct .unpack ("<H" , _read_exact (fp , 2 ))
478
+ header = b"" .join (header_parts )
479
+ true_crc = zlib .crc32 (header ) & 0xFFFF
480
+ if header_crc != true_crc :
481
+ raise BadGzipFile (f"Corrupted gzip header. Checksums do not "
482
+ f"match: { true_crc :04x} != { header_crc :04x} " )
452
483
return last_mtime
453
484
454
485
0 commit comments