throw error on partial header reading stream
authorPhilipp Gesang <philipp.gesang@intra2net.com>
Mon, 10 Apr 2017 13:01:56 +0000 (15:01 +0200)
committerThomas Jarosch <thomas.jarosch@intra2net.com>
Mon, 2 Apr 2018 11:34:08 +0000 (13:34 +0200)
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
deltatar/tarfile.py

index 99eaf3a..834b8ac 100755 (executable)
@@ -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)
 
 
index 704ecc6..e6099be 100644 (file)
@@ -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)