diff options
author | Antoine Pitrou <solipsis@pitrou.net> | 2010-08-12 15:25:51 (GMT) |
---|---|---|
committer | Antoine Pitrou <solipsis@pitrou.net> | 2010-08-12 15:25:51 (GMT) |
commit | e1436d1092f26a4329a2b48c48539d5845ddce32 (patch) | |
tree | 06fe4190de13a77557fe7c9e75cd8549a98ee4d2 /Lib/zipfile.py | |
parent | 3523443f77521ae0365ea2047a1c18491c1ce3cb (diff) | |
download | cpython-e1436d1092f26a4329a2b48c48539d5845ddce32.zip cpython-e1436d1092f26a4329a2b48c48539d5845ddce32.tar.gz cpython-e1436d1092f26a4329a2b48c48539d5845ddce32.tar.bz2 |
Merged revisions 83959-83960 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/branches/py3k
........
r83959 | antoine.pitrou | 2010-08-12 17:11:50 +0200 (jeu., 12 août 2010) | 5 lines
Issue #7467: when a file from a ZIP archive, its CRC is checked and a
BadZipfile error is raised if it doesn't match (as used to be the
case in Python 2.5 and earlier).
........
r83960 | antoine.pitrou | 2010-08-12 17:15:01 +0200 (jeu., 12 août 2010) | 3 lines
Typo.
........
Diffstat (limited to 'Lib/zipfile.py')
-rw-r--r-- | Lib/zipfile.py | 25 |
1 files changed, 23 insertions, 2 deletions
diff --git a/Lib/zipfile.py b/Lib/zipfile.py index ece538e..ef19a28 100644 --- a/Lib/zipfile.py +++ b/Lib/zipfile.py @@ -493,6 +493,12 @@ class ZipExtFile(io.BufferedIOBase): self.mode = mode self.name = zipinfo.filename + if hasattr(zipinfo, 'CRC'): + self._expected_crc = zipinfo.CRC + self._running_crc = crc32(b'') & 0xffffffff + else: + self._expected_crc = None + def readline(self, limit=-1): """Read and return a line from the stream. @@ -570,6 +576,16 @@ class ZipExtFile(io.BufferedIOBase): return buf + def _update_crc(self, newdata, eof): + # Update the CRC using the given data. + if self._expected_crc is None: + # No need to compute the CRC if we don't have a reference value + return + self._running_crc = crc32(newdata, self._running_crc) & 0xffffffff + # Check the CRC if we're at the end of the file + if eof and self._running_crc != self._expected_crc: + raise BadZipfile("Bad CRC-32 for file %r" % self.name) + def read1(self, n): """Read up to n bytes with at most one read() system call.""" @@ -593,6 +609,7 @@ class ZipExtFile(io.BufferedIOBase): data = ''.join(map(self._decrypter, data)) if self._compress_type == ZIP_STORED: + self._update_crc(data, eof=(self._compress_left==0)) self._readbuffer = self._readbuffer[self._offset:] + data self._offset = 0 else: @@ -608,9 +625,11 @@ class ZipExtFile(io.BufferedIOBase): ) self._unconsumed = self._decompressor.unconsumed_tail - if len(self._unconsumed) == 0 and self._compress_left == 0: + eof = len(self._unconsumed) == 0 and self._compress_left == 0 + if eof: data += self._decompressor.flush() + self._update_crc(data, eof=eof) self._readbuffer = self._readbuffer[self._offset:] + data self._offset = 0 @@ -1349,7 +1368,9 @@ def main(args = None): print USAGE sys.exit(1) zf = ZipFile(args[1], 'r') - zf.testzip() + badfile = zf.testzip() + if badfile: + print("The following enclosed file is corrupted: {!r}".format(badfile)) print "Done testing" elif args[0] == '-e': |