Handle zip64 extra fields better

Test: check_target_files_signatures
Bug: 283033491
(cherry picked from https://android-review.googlesource.com/q/commit:1e774245a4dd2763545827d65462e5c115eecb63)
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:e66c973a36339484e8fa59c37c9005badca62a5d)
Merged-In: I7da89f8389c09cc99201cff342483c158bd7e9c1
Change-Id: I7da89f8389c09cc99201cff342483c158bd7e9c1
This commit is contained in:
Kelvin Zhang
2023-06-17 09:18:15 -07:00
committed by Android Build Coastguard Worker
parent 1836ac3ff7
commit f604d01ba4
2 changed files with 19 additions and 4 deletions

View File

@@ -241,7 +241,8 @@ class APK(object):
# Signer (minSdkVersion=24, maxSdkVersion=32) certificate SHA-1 digest: 19da94896ce4078c38ca695701f1dec741ec6d67
# ...
certs_info = {}
certificate_regex = re.compile(r"(Signer (?:#[0-9]+|\(.*\))) (certificate .*):(.*)")
certificate_regex = re.compile(
r"(Signer (?:#[0-9]+|\(.*\))) (certificate .*):(.*)")
for line in output.splitlines():
m = certificate_regex.match(line)
if not m:
@@ -312,7 +313,7 @@ class TargetFiles(object):
# This is the list of wildcards of files we extract from |filename|.
apk_extensions = ['*.apk', '*.apex']
with zipfile.ZipFile(filename) as input_zip:
with zipfile.ZipFile(filename, "r") as input_zip:
self.certmap, compressed_extension = common.ReadApkCerts(input_zip)
if compressed_extension:
apk_extensions.append('*.apk' + compressed_extension)

View File

@@ -2123,9 +2123,23 @@ def UnzipToDir(filename, dirname, patterns=None):
# to indicate the actual local header offset.
# As of python3.11, python does not handle zip64 central directories
# correctly, so we will manually do the parsing here.
# ZIP64 central directory extra field has two required fields:
# 2 bytes header ID and 2 bytes size field. Thes two require fields have
# a total size of 4 bytes. Then it has three other 8 bytes field, followed
# by a 4 byte disk number field. The last disk number field is not required
# to be present, but if it is present, the total size of extra field will be
# divisible by 8(because 2+2+4+8*n is always going to be multiple of 8)
# Most extra fields are optional, but when they appear, their must appear
# in the order defined by zip64 spec. Since file header offset is the 2nd
# to last field in zip64 spec, it will only be at last 8 bytes or last 12-4
# bytes, depending on whether disk number is present.
for entry in entries:
if entry.header_offset == 0xFFFFFFFF and len(entry.extra) >= 28:
entry.header_offset = int.from_bytes(entry.extra[20:28], "little")
if entry.header_offset == 0xFFFFFFFF:
if len(entry.extra) % 8 == 0:
entry.header_offset = int.from_bytes(entry.extra[-12:-4], "little")
else:
entry.header_offset = int.from_bytes(entry.extra[-8:], "little")
if patterns is not None:
filtered = [info for info in entries if any(
[fnmatch.fnmatch(info.filename, p) for p in patterns])]