aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKelvin Zhang <zhangkelvin@google.com>2023-06-14 12:53:29 -0700
committerKelvin Zhang <zhangkelvin@google.com>2023-07-17 14:08:16 -0700
commit3c739f18475a9d31be299f3016dddc6a5ac02e16 (patch)
tree6d80e34f0bd6028157f7132cc76e6253fb69afd6
parent0bf992ee0595727b4a2c563fd5023287727dd8b3 (diff)
downloadbuild-3c739f18475a9d31be299f3016dddc6a5ac02e16.tar.gz
Fix python3.11's support for zip64
Bug: 283033491 Test: check_target_files_signatures -v -l (cherry picked from https://android-review.googlesource.com/q/commit:38d0c373ac9e0f00c6e677c41bbc85f0e364ba02) Merged-In: I9c1a5346e3a5f3920242dc9a5268d999f50a4937 Change-Id: I9c1a5346e3a5f3920242dc9a5268d999f50a4937
-rw-r--r--tools/releasetools/common.py19
1 files changed, 15 insertions, 4 deletions
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index 420be97efd..f2e77756b0 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -2114,17 +2114,28 @@ def UnzipToDir(filename, dirname, patterns=None):
"""
with zipfile.ZipFile(filename, allowZip64=True, mode="r") as input_zip:
# Filter out non-matching patterns. unzip will complain otherwise.
+ entries = input_zip.infolist()
+ # b/283033491
+ # Per https://en.wikipedia.org/wiki/ZIP_(file_format)#Central_directory_file_header
+ # In zip64 mode, central directory record's header_offset field might be
+ # set to 0xFFFFFFFF if header offset is > 2^32. In this case, the extra
+ # fields will contain an 8 byte little endian integer at offset 20
+ # 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.
+ 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 patterns is not None:
- names = input_zip.namelist()
- filtered = [name for name in names if any(
- [fnmatch.fnmatch(name, p) for p in patterns])]
+ filtered = [info for info in entries if any(
+ [fnmatch.fnmatch(info.filename, p) for p in patterns])]
# There isn't any matching files. Don't unzip anything.
if not filtered:
return
input_zip.extractall(dirname, filtered)
else:
- input_zip.extractall(dirname)
+ input_zip.extractall(dirname, entries)
def UnzipTemp(filename, patterns=None):