Skip to content

Commit cc555cf

Browse files
committed
Rework using try...except
The previous implementation introduced a behavior change: a field with truncated data was always kept, while it had been filtered by passed `field_id`. Go back to use the try...except to adhere the original behavior as the original `_Extra.split()`. Also add a test to explicitly check for such case. Benchmark shows this implementation improves performance.
1 parent a693084 commit cc555cf

2 files changed

Lines changed: 19 additions & 8 deletions

File tree

Lib/test/test_zipfile/test_core.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5884,6 +5884,20 @@ def test_multiples(self):
58845884
self.assertEqual(b, self.strip_extra(a+b+a, (self.ZIP64_EXTRA,)))
58855885
self.assertEqual(b, self.strip_extra(b+a+a, (self.ZIP64_EXTRA,)))
58865886

5887+
def test_truncated_data_for_stripped_id(self):
5888+
s = struct.Struct("<HH")
5889+
a = s.pack(self.ZIP64_EXTRA, 3) + b"a"
5890+
b = s.pack(2, 2) + b"bb"
5891+
5892+
self.assertEqual(b, self.strip_extra(b+a, (self.ZIP64_EXTRA,)))
5893+
5894+
def test_truncated_data_for_nonstripped_id(self):
5895+
s = struct.Struct("<HH")
5896+
a = s.pack(self.ZIP64_EXTRA, 3) + b"a"
5897+
b = s.pack(2, 2) + b"bb"
5898+
5899+
self.assertEqual(b+a, self.strip_extra(b+a, (3,)))
5900+
58875901
def test_too_short(self):
58885902
self.assertEqual(b"", self.strip_extra(b"", (self.ZIP64_EXTRA,)))
58895903
self.assertEqual(b"z", self.strip_extra(b"z", (self.ZIP64_EXTRA,)))

Lib/zipfile/__init__.py

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2718,18 +2718,15 @@ def _strip_extra_fields(data, field_ids):
27182718

27192719
data_len = len(data)
27202720
pos = 0
2721-
while pos + 4 <= data_len:
2722-
xid, xlen = struct.unpack_from('<HH', data, pos)
2723-
if pos + 4 + xlen > data_len:
2724-
break
2721+
while pos < data_len:
2722+
try:
2723+
xid, xlen = struct.unpack_from('<HH', data, pos)
2724+
except struct.error:
2725+
xid, xlen = None, 0
27252726
if xid not in field_ids:
27262727
result.extend(data[pos:pos + 4 + xlen])
27272728
pos += 4 + xlen
27282729

2729-
# keep remaining trailing bytes (e.g. truncated or malformed data)
2730-
if pos < data_len:
2731-
result.extend(data[pos:])
2732-
27332730
return result
27342731

27352732
def _fpclose(self, fp):

0 commit comments

Comments
 (0)