Skip to content

Commit 12d27d8

Browse files
thatchpython-sidebar
authored andcommitted
pythongh-88233: zipfile: handle extras after a zip64 extra (pythonGH-96161)
Previously, any data _after_ the zip64 extra would be removed. With many new tests. Fixes python#88233 Automerge-Triggered-By: GH:jaraco
1 parent 57cde1f commit 12d27d8

File tree

3 files changed

+66
-0
lines changed

3 files changed

+66
-0
lines changed

Lib/test/test_zipfile/test_core.py

+62
Original file line numberDiff line numberDiff line change
@@ -3010,5 +3010,67 @@ def test_cli_with_metadata_encoding_extract(self):
30103010
self.assertIn(name, listing)
30113011

30123012

3013+
class StripExtraTests(unittest.TestCase):
3014+
# Note: all of the "z" characters are technically invalid, but up
3015+
# to 3 bytes at the end of the extra will be passed through as they
3016+
# are too short to encode a valid extra.
3017+
3018+
ZIP64_EXTRA = 1
3019+
3020+
def test_no_data(self):
3021+
s = struct.Struct("<HH")
3022+
a = s.pack(self.ZIP64_EXTRA, 0)
3023+
b = s.pack(2, 0)
3024+
c = s.pack(3, 0)
3025+
3026+
self.assertEqual(b'', zipfile._strip_extra(a, (self.ZIP64_EXTRA,)))
3027+
self.assertEqual(b, zipfile._strip_extra(b, (self.ZIP64_EXTRA,)))
3028+
self.assertEqual(
3029+
b+b"z", zipfile._strip_extra(b+b"z", (self.ZIP64_EXTRA,)))
3030+
3031+
self.assertEqual(b+c, zipfile._strip_extra(a+b+c, (self.ZIP64_EXTRA,)))
3032+
self.assertEqual(b+c, zipfile._strip_extra(b+a+c, (self.ZIP64_EXTRA,)))
3033+
self.assertEqual(b+c, zipfile._strip_extra(b+c+a, (self.ZIP64_EXTRA,)))
3034+
3035+
def test_with_data(self):
3036+
s = struct.Struct("<HH")
3037+
a = s.pack(self.ZIP64_EXTRA, 1) + b"a"
3038+
b = s.pack(2, 2) + b"bb"
3039+
c = s.pack(3, 3) + b"ccc"
3040+
3041+
self.assertEqual(b"", zipfile._strip_extra(a, (self.ZIP64_EXTRA,)))
3042+
self.assertEqual(b, zipfile._strip_extra(b, (self.ZIP64_EXTRA,)))
3043+
self.assertEqual(
3044+
b+b"z", zipfile._strip_extra(b+b"z", (self.ZIP64_EXTRA,)))
3045+
3046+
self.assertEqual(b+c, zipfile._strip_extra(a+b+c, (self.ZIP64_EXTRA,)))
3047+
self.assertEqual(b+c, zipfile._strip_extra(b+a+c, (self.ZIP64_EXTRA,)))
3048+
self.assertEqual(b+c, zipfile._strip_extra(b+c+a, (self.ZIP64_EXTRA,)))
3049+
3050+
def test_multiples(self):
3051+
s = struct.Struct("<HH")
3052+
a = s.pack(self.ZIP64_EXTRA, 1) + b"a"
3053+
b = s.pack(2, 2) + b"bb"
3054+
3055+
self.assertEqual(b"", zipfile._strip_extra(a+a, (self.ZIP64_EXTRA,)))
3056+
self.assertEqual(b"", zipfile._strip_extra(a+a+a, (self.ZIP64_EXTRA,)))
3057+
self.assertEqual(
3058+
b"z", zipfile._strip_extra(a+a+b"z", (self.ZIP64_EXTRA,)))
3059+
self.assertEqual(
3060+
b+b"z", zipfile._strip_extra(a+a+b+b"z", (self.ZIP64_EXTRA,)))
3061+
3062+
self.assertEqual(b, zipfile._strip_extra(a+a+b, (self.ZIP64_EXTRA,)))
3063+
self.assertEqual(b, zipfile._strip_extra(a+b+a, (self.ZIP64_EXTRA,)))
3064+
self.assertEqual(b, zipfile._strip_extra(b+a+a, (self.ZIP64_EXTRA,)))
3065+
3066+
def test_too_short(self):
3067+
self.assertEqual(b"", zipfile._strip_extra(b"", (self.ZIP64_EXTRA,)))
3068+
self.assertEqual(b"z", zipfile._strip_extra(b"z", (self.ZIP64_EXTRA,)))
3069+
self.assertEqual(
3070+
b"zz", zipfile._strip_extra(b"zz", (self.ZIP64_EXTRA,)))
3071+
self.assertEqual(
3072+
b"zzz", zipfile._strip_extra(b"zzz", (self.ZIP64_EXTRA,)))
3073+
3074+
30133075
if __name__ == "__main__":
30143076
unittest.main()

Lib/zipfile/__init__.py

+2
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,8 @@ def _strip_extra(extra, xids):
207207
i = j
208208
if not modified:
209209
return extra
210+
if start != len(extra):
211+
buffer.append(extra[start:])
210212
return b''.join(buffer)
211213

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

0 commit comments

Comments
 (0)