Skip to content

Commit

Permalink
[3.10] gh-88233: zipfile: handle extras after a zip64 extra (GH-96161) (
Browse files Browse the repository at this point in the history
#102087)

Previously, any data _after_ the zip64 extra would be removed.

With many new tests.

Fixes GH-88233
(cherry picked from commit 59e86ca)

Co-authored-by: Tim Hatch <[email protected]>
  • Loading branch information
miss-islington and thatch authored Mar 28, 2023
1 parent 3288923 commit d445147
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 0 deletions.
62 changes: 62 additions & 0 deletions Lib/test/test_zipfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -3221,5 +3221,67 @@ def test_extract_orig_with_implied_dirs(self, alpharep):
zf.extractall(source_path.parent)


class StripExtraTests(unittest.TestCase):
# Note: all of the "z" characters are technically invalid, but up
# to 3 bytes at the end of the extra will be passed through as they
# are too short to encode a valid extra.

ZIP64_EXTRA = 1

def test_no_data(self):
s = struct.Struct("<HH")
a = s.pack(self.ZIP64_EXTRA, 0)
b = s.pack(2, 0)
c = s.pack(3, 0)

self.assertEqual(b'', zipfile._strip_extra(a, (self.ZIP64_EXTRA,)))
self.assertEqual(b, zipfile._strip_extra(b, (self.ZIP64_EXTRA,)))
self.assertEqual(
b+b"z", zipfile._strip_extra(b+b"z", (self.ZIP64_EXTRA,)))

self.assertEqual(b+c, zipfile._strip_extra(a+b+c, (self.ZIP64_EXTRA,)))
self.assertEqual(b+c, zipfile._strip_extra(b+a+c, (self.ZIP64_EXTRA,)))
self.assertEqual(b+c, zipfile._strip_extra(b+c+a, (self.ZIP64_EXTRA,)))

def test_with_data(self):
s = struct.Struct("<HH")
a = s.pack(self.ZIP64_EXTRA, 1) + b"a"
b = s.pack(2, 2) + b"bb"
c = s.pack(3, 3) + b"ccc"

self.assertEqual(b"", zipfile._strip_extra(a, (self.ZIP64_EXTRA,)))
self.assertEqual(b, zipfile._strip_extra(b, (self.ZIP64_EXTRA,)))
self.assertEqual(
b+b"z", zipfile._strip_extra(b+b"z", (self.ZIP64_EXTRA,)))

self.assertEqual(b+c, zipfile._strip_extra(a+b+c, (self.ZIP64_EXTRA,)))
self.assertEqual(b+c, zipfile._strip_extra(b+a+c, (self.ZIP64_EXTRA,)))
self.assertEqual(b+c, zipfile._strip_extra(b+c+a, (self.ZIP64_EXTRA,)))

def test_multiples(self):
s = struct.Struct("<HH")
a = s.pack(self.ZIP64_EXTRA, 1) + b"a"
b = s.pack(2, 2) + b"bb"

self.assertEqual(b"", zipfile._strip_extra(a+a, (self.ZIP64_EXTRA,)))
self.assertEqual(b"", zipfile._strip_extra(a+a+a, (self.ZIP64_EXTRA,)))
self.assertEqual(
b"z", zipfile._strip_extra(a+a+b"z", (self.ZIP64_EXTRA,)))
self.assertEqual(
b+b"z", zipfile._strip_extra(a+a+b+b"z", (self.ZIP64_EXTRA,)))

self.assertEqual(b, zipfile._strip_extra(a+a+b, (self.ZIP64_EXTRA,)))
self.assertEqual(b, zipfile._strip_extra(a+b+a, (self.ZIP64_EXTRA,)))
self.assertEqual(b, zipfile._strip_extra(b+a+a, (self.ZIP64_EXTRA,)))

def test_too_short(self):
self.assertEqual(b"", zipfile._strip_extra(b"", (self.ZIP64_EXTRA,)))
self.assertEqual(b"z", zipfile._strip_extra(b"z", (self.ZIP64_EXTRA,)))
self.assertEqual(
b"zz", zipfile._strip_extra(b"zz", (self.ZIP64_EXTRA,)))
self.assertEqual(
b"zzz", zipfile._strip_extra(b"zzz", (self.ZIP64_EXTRA,)))


if __name__ == "__main__":
unittest.main()
2 changes: 2 additions & 0 deletions Lib/zipfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,8 @@ def _strip_extra(extra, xids):
i = j
if not modified:
return extra
if start != len(extra):
buffer.append(extra[start:])
return b''.join(buffer)

def _check_zipfile(fp):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Correctly preserve "extra" fields in ``zipfile`` regardless of their
ordering relative to a zip64 "extra."

0 comments on commit d445147

Please sign in to comment.