From 232a7d2f911402eb533a9c8a8f0e2b57e29ce077 Mon Sep 17 00:00:00 2001 From: Daniel Hillier Date: Fri, 14 May 2021 14:13:36 +1000 Subject: [PATCH 1/2] bpo-44128: Refactor ZipExtFile init and re-init after seek --- Lib/zipfile.py | 66 ++++++++++++++++++++++++-------------------------- 1 file changed, 32 insertions(+), 34 deletions(-) diff --git a/Lib/zipfile.py b/Lib/zipfile.py index d99c0d76977750..ebeb6100c1887d 100644 --- a/Lib/zipfile.py +++ b/Lib/zipfile.py @@ -787,19 +787,12 @@ class ZipExtFile(io.BufferedIOBase): def __init__(self, fileobj, mode, zipinfo, pwd=None, close_fileobj=False): + self._zinfo = zipinfo self._fileobj = fileobj self._pwd = pwd self._close_fileobj = close_fileobj self._compress_type = zipinfo.compress_type - self._compress_left = zipinfo.compress_size - self._left = zipinfo.file_size - - self._decompressor = _get_decompressor(self._compress_type) - - self._eof = False - self._readbuffer = b'' - self._offset = 0 self.newlines = None @@ -808,33 +801,37 @@ def __init__(self, fileobj, mode, zipinfo, pwd=None, if hasattr(zipinfo, 'CRC'): self._expected_crc = zipinfo.CRC - self._running_crc = crc32(b'') else: self._expected_crc = None self._seekable = False try: if fileobj.seekable(): - self._orig_compress_start = fileobj.tell() - self._orig_compress_size = zipinfo.compress_size self._orig_file_size = zipinfo.file_size - self._orig_start_crc = self._running_crc self._seekable = True except AttributeError: pass self._decrypter = None - if pwd: - if zipinfo.flag_bits & 0x8: - # compare against the file type from extended local headers - check_byte = (zipinfo._raw_time >> 8) & 0xff - else: - # compare against the CRC otherwise - check_byte = (zipinfo.CRC >> 24) & 0xff - h = self._init_decrypter() - if h != check_byte: - raise RuntimeError("Bad password for file %r" % zipinfo.orig_filename) + # Compress start is the byte after the 'local file header' ie. the + # start of 'encryption header' section, if present, or + # 'file data' otherwise. + self._compress_start = fileobj.tell() + self.read_init() + + def read_init(self): + """Set or reset this ZipExtFile to read from the start of the file""" + self._running_crc = crc32(b'') + self._compress_left = self._zinfo.compress_size + self._left = self._zinfo.file_size + self._eof = False + self._readbuffer = b'' + self._offset = 0 + + if self._pwd: + self._init_decrypter() + self._decompressor = _get_decompressor(self._compress_type) def _init_decrypter(self): self._decrypter = _ZipDecrypter(self._pwd) @@ -845,7 +842,17 @@ def _init_decrypter(self): # and is used to check the correctness of the password. header = self._fileobj.read(12) self._compress_left -= 12 - return self._decrypter(header)[11] + computed_check_byte = self._decrypter(header)[11] + + if self._zinfo.flag_bits & 0x8: + # compare against the file type from extended local headers + check_byte = (self._zinfo._raw_time >> 8) & 0xff + else: + # compare against the CRC otherwise + check_byte = (self._zinfo.CRC >> 24) & 0xff + + if computed_check_byte != check_byte: + raise RuntimeError("Bad password for file %r" % self._zinfo.orig_filename) def __repr__(self): result = ['<%s.%s' % (self.__class__.__module__, @@ -1072,17 +1079,8 @@ def seek(self, offset, whence=0): read_offset = 0 elif read_offset < 0: # Position is before the current position. Reset the ZipExtFile - self._fileobj.seek(self._orig_compress_start) - self._running_crc = self._orig_start_crc - self._compress_left = self._orig_compress_size - self._left = self._orig_file_size - self._readbuffer = b'' - self._offset = 0 - self._decompressor = _get_decompressor(self._compress_type) - self._eof = False - read_offset = new_pos - if self._decrypter is not None: - self._init_decrypter() + self._fileobj.seek(self._compress_start) + self.read_init() while read_offset > 0: read_len = min(self.MAX_SEEK_READ, read_offset) From a889a80653df4fc7c0d0b301b52389d00e401b5d Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Fri, 14 May 2021 04:37:54 +0000 Subject: [PATCH 2/2] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20blu?= =?UTF-8?q?rb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../NEWS.d/next/Library/2021-05-14-04-37-51.bpo-44128.cxicgo.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Library/2021-05-14-04-37-51.bpo-44128.cxicgo.rst diff --git a/Misc/NEWS.d/next/Library/2021-05-14-04-37-51.bpo-44128.cxicgo.rst b/Misc/NEWS.d/next/Library/2021-05-14-04-37-51.bpo-44128.cxicgo.rst new file mode 100644 index 00000000000000..b6da75e9c0a198 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-05-14-04-37-51.bpo-44128.cxicgo.rst @@ -0,0 +1 @@ +Minor refactor of zipfile.ZipExtFile \ No newline at end of file pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy