summaryrefslogtreecommitdiffstats
path: root/Lib/zipfile.py
diff options
context:
space:
mode:
authorAntoine Pitrou <solipsis@pitrou.net>2010-08-12 15:11:50 (GMT)
committerAntoine Pitrou <solipsis@pitrou.net>2010-08-12 15:11:50 (GMT)
commit7c8bcb6f923c860986477660f634ea63f103ebaa (patch)
treeee42c1ab3544d27526c521851befcac995f1d421 /Lib/zipfile.py
parentd4efbf90d24405f89df07f6e575e3572a0516e85 (diff)
downloadcpython-7c8bcb6f923c860986477660f634ea63f103ebaa.zip
cpython-7c8bcb6f923c860986477660f634ea63f103ebaa.tar.gz
cpython-7c8bcb6f923c860986477660f634ea63f103ebaa.tar.bz2
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).
Diffstat (limited to 'Lib/zipfile.py')
-rw-r--r--Lib/zipfile.py25
1 files changed, 23 insertions, 2 deletions
diff --git a/Lib/zipfile.py b/Lib/zipfile.py
index f81cc8b..c47c3cc 100644
--- a/Lib/zipfile.py
+++ b/Lib/zipfile.py
@@ -492,6 +492,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.
@@ -569,6 +575,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."""
@@ -592,6 +608,7 @@ class ZipExtFile(io.BufferedIOBase):
data = bytes(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:
@@ -607,9 +624,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
@@ -1380,7 +1399,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':