From 8a8ac4693ad2e603f002405dede02372d26dc19f Mon Sep 17 00:00:00 2001 From: Philipp Gesang Date: Mon, 10 Apr 2017 15:01:56 +0200 Subject: [PATCH] throw error on partial header reading stream MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Throw the EOF exception only if the stream ends exactly at an object boundary. Otherwise, when less then sizeof(hdr) bytes are returned from read(), throw InvalidHeader to indicate a malformed file. This keeps EOF a “benign” exception. --- deltatar/crypto.py | 11 ++++++----- deltatar/tarfile.py | 17 +++++++++-------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/deltatar/crypto.py b/deltatar/crypto.py index 99eaf3a..834b8ac 100755 --- a/deltatar/crypto.py +++ b/deltatar/crypto.py @@ -95,7 +95,7 @@ class EndOfFile (Exception): """Reached EOF.""" remainder = 0 msg = 0 - def __init__ (self, n, msg=None): + def __init__ (self, n=None, msg=None): self.remainder = n self.msg = msg @@ -256,10 +256,11 @@ def hdr_read (data): def hdr_read_stream (instr): data = instr.read(PDTCRYPT_HDR_SIZE) ldata = len (data) - if ldata != PDTCRYPT_HDR_SIZE: - raise EndOfFile (ldata, - "read: expected %d B, received %d B" - % (PDTCRYPT_HDR_SIZE, len (data))) + if ldata == 0: + raise EndOfFile + elif ldata != PDTCRYPT_HDR_SIZE: + raise InvalidHeader ("hdr_read_stream: expected %d B, received %d B" + % (PDTCRYPT_HDR_SIZE, ldata)) return hdr_read (data) diff --git a/deltatar/tarfile.py b/deltatar/tarfile.py index 704ecc6..e6099be 100644 --- a/deltatar/tarfile.py +++ b/deltatar/tarfile.py @@ -767,18 +767,16 @@ class _Stream: self.lasthdr = self.fileobj.tell () try: hdr = crypto.hdr_read_stream (self.fileobj) - except crypto.EndOfFile as exn: - if exn.remainder == 0: - raise EOFHeaderError("end of file header") - raise DecryptionError ("Crypto.hdr_read_stream(): hit EOF " - "reading header %r" % (self.fileobj)) \ - from exn + except crypto.EndOfFile: + return False except crypto.InvalidHeader: raise DecryptionError ("Crypto.hdr_read_stream(): error “%s” " "processing %r" % (hdr, self.fileobj)) \ from exn self.remainder = hdr ["ctsize"] # distance to next header - return self.encryption.next (hdr) + self.encryption.next (hdr) + + return True def _finalize_read_encrypt (self): @@ -914,7 +912,10 @@ class _Stream: if self.encryption is not None: if self.remainder <= 0: # prepare next object - self._init_read_encrypt () + if self._init_read_encrypt () is False: # EOF + buf = None + break # while + # only read up to the end of the encrypted object todo = min (size, self.remainder) buf = self.fileobj.read(todo) -- 1.7.1