Ensure output files are zip64-compliant (again)

PR #110 fixed this incorrectly. I misinterpreted "set to zero in the
local header" from §4.4.4 in the spec as referring to the two 32-bit
size fields in the local header. However, the spec considers the zip64
extra record as part of the local header. The correct behavior for
writing zip64 entries to unseekable files is 0xffffffff in the 32-bit
local header size fields (to enable zip64), 0 in the zip64 extra record
(due to streaming writes), and the actual sizes in the data descriptor.

Fixes: #109

Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
This commit is contained in:
Andrew Gunnerson
2023-07-03 16:26:30 -04:00
parent 056359c853
commit bf53859bcd
2 changed files with 14 additions and 11 deletions
+12 -9
View File
@@ -259,22 +259,25 @@ def strip_bad_extra_fields(extra):
@contextlib.contextmanager
def fix_streaming_local_header_sizes():
'''
Some Python versions have a regression [1] where the local file header's
compressed and uncompressed size fields are incorrectly set to 0xffffffff
when data descriptors are used. This function monkey patches zipfile's
local file header serialization to manually fix this issue.
[1] https://github.com/python/cpython/issues/106218
Older Python versions don't set the local header's two 32-bit size fields to
0xffffffff when writing a zip64 entry to an unseekable file. This function
monkey patches zipfile's local file header serialization to manually fix
this issue.
'''
orig = zipfile.ZipInfo.FileHeader
def wrapper(*args, **kwargs):
blob = orig(*args, **kwargs)
zip64 = kwargs.get('zip64')
if zip64 is None:
zip64 = args[0].file_size > zipfile.ZIP64_LIMIT or \
args[0].compress_size > zipfile.ZIP64_LIMIT
fields = list(struct.unpack_from(zipfile.structFileHeader, blob))
if fields[3] & (1 << 3):
fields[8] = 0
fields[9] = 0
if fields[3] & (1 << 3) and zip64:
fields[8] = 0xffffffff
fields[9] = 0xffffffff
return struct.pack(zipfile.structFileHeader, *fields) + \
blob[zipfile.sizeFileHeader:]
+2 -2
View File
@@ -143,8 +143,8 @@ device:
full: 929f892fbd70699cf7f118a119aac1ae1b86351e1ada17715666fa4401e63472
stripped: 4eabaf79b6c2b5df305e3ecdc2b9570c0dd27350b4e8d6434584000c4989ff3d
patched:
full: c152a9c49a81d521b7652662807d017655cbb999d503f869599753ab907b2133
stripped: 15e04f3fcca564384c2258c9a93cd5986d82f5b8b68d08a4e067fa7aae0b3dcc
full: 2c44c34fa25feda472ded5ab693e9b7fdd746c770ecfcc0e3b95d06a1fe35a61
stripped: 24a8cbd86a3221aef9cca0751e9218a2221f33a8e1a34f3a60a10473fc18d495
avb_images:
boot.img: ec703e143c24e7eb5b2eb96beb1d4342c1dd2179b12612d41430b1b55e7dec0f
recovery.img: 2ff62bc52a5900eb170cc44df0f0ee8062ee6dcb48ecf1899ac556145161f53c