Commit d2b6b7fa authored by Antoine Pitrou's avatar Antoine Pitrou

Issue #9837: The read() method of ZipExtFile objects (as returned by

ZipFile.open()) could return more bytes than requested.
parent 63010ec6
...@@ -939,6 +939,26 @@ class OtherTests(unittest.TestCase): ...@@ -939,6 +939,26 @@ class OtherTests(unittest.TestCase):
def test_read_with_bad_crc_deflated(self): def test_read_with_bad_crc_deflated(self):
self.check_read_with_bad_crc(zipfile.ZIP_DEFLATED) self.check_read_with_bad_crc(zipfile.ZIP_DEFLATED)
def check_read_return_size(self, compression):
# Issue #9837: ZipExtFile.read() shouldn't return more bytes
# than requested.
for test_size in (1, 4095, 4096, 4097, 16384):
file_size = test_size + 1
junk = b''.join(struct.pack('B', randint(0, 255))
for x in range(file_size))
with zipfile.ZipFile(io.BytesIO(), "w", compression) as zipf:
zipf.writestr('foo', junk)
with zipf.open('foo', 'r') as fp:
buf = fp.read(test_size)
self.assertEqual(len(buf), test_size)
def test_read_return_size_stored(self):
self.check_read_return_size(zipfile.ZIP_STORED)
@skipUnless(zlib, "requires zlib")
def test_read_return_size_deflated(self):
self.check_read_return_size(zipfile.ZIP_DEFLATED)
def tearDown(self): def tearDown(self):
unlink(TESTFN) unlink(TESTFN)
unlink(TESTFN2) unlink(TESTFN2)
......
...@@ -564,17 +564,20 @@ class ZipExtFile(io.BufferedIOBase): ...@@ -564,17 +564,20 @@ class ZipExtFile(io.BufferedIOBase):
"""Read and return up to n bytes. """Read and return up to n bytes.
If the argument is omitted, None, or negative, data is read and returned until EOF is reached.. If the argument is omitted, None, or negative, data is read and returned until EOF is reached..
""" """
buf = b'' buf = b''
while n < 0 or n is None or n > len(buf): if n is None:
n = -1
while True:
if n < 0:
data = self.read1(n) data = self.read1(n)
elif n > len(buf):
data = self.read1(n - len(buf))
else:
return buf
if len(data) == 0: if len(data) == 0:
return buf return buf
buf += data buf += data
return buf
def _update_crc(self, newdata, eof): def _update_crc(self, newdata, eof):
# Update the CRC using the given data. # Update the CRC using the given data.
if self._expected_crc is None: if self._expected_crc is None:
......
...@@ -32,6 +32,9 @@ Core and Builtins ...@@ -32,6 +32,9 @@ Core and Builtins
Library Library
------- -------
- Issue #9837: The read() method of ZipExtFile objects (as returned by
ZipFile.open()) could return more bytes than requested.
- Issue #9826: OrderedDict.__repr__ can now handle self-referential - Issue #9826: OrderedDict.__repr__ can now handle self-referential
values: d['x'] = d. values: d['x'] = d.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment