allow for detecting overlapping objects with tarfile
authorPhilipp Gesang <philipp.gesang@intra2net.com>
Mon, 28 Aug 2017 15:56:33 +0000 (17:56 +0200)
committerThomas Jarosch <thomas.jarosch@intra2net.com>
Mon, 2 Apr 2018 11:34:09 +0000 (13:34 +0200)
deltatar/crypto.py
deltatar/tarfile.py

index a381d2b..41f0cbd 100755 (executable)
@@ -655,18 +655,21 @@ def readable_objects_offsets (ifd, secret, cands):
     readable PDTCRYPT objects.
     """
     good = []
-    nobj = 0
-    for cand in cands:
-        nobj += 1
+
+    for i, cand in enumerate (cands):
         vdt, hdr = inspect_hdr (ifd, cand)
         if vdt == HDR_CAND_JUNK:
             pass # ignore unreadable ones
         elif vdt in [HDR_CAND_GOOD, HDR_CAND_FISHY]:
+            ctsize =  hdr ["ctsize"]
             off0 = cand + PDTCRYPT_HDR_SIZE
-            ok = try_decrypt (ifd, off0, hdr, secret) == hdr ["ctsize"]
+            ok = try_decrypt (ifd, off0, hdr, secret) == ctsize
             if ok is True:
-                good.append (cand)
-    return good
+                good.append ((cand, off0 + ctsize))
+
+    overlap = find_overlaps (good)
+
+    return [ g [0] for g in good ]
 
 
 def reconstruct_offsets (fname, secret):
index c63bb23..31e46b9 100644 (file)
@@ -1026,7 +1026,14 @@ class _Stream:
                                 t.append (buf)
                             if len (t) > 0:
                                 break
-                            raise
+                        raise
+                    except ReadError: # gzip troubles
+                        if self.tolerance == TOLERANCE_RESCUE:
+                            if len (buf) > 0:
+                                t.append (buf)
+                            if len (t) > 0:
+                                break
+                        raise
                     except EndOfFile:
                         # happens at the end of the file
                         pass
@@ -1082,13 +1089,21 @@ class _Stream:
                 if self.tolerance == TOLERANCE_STRICT:
                     raise
                 self.encryption.drop ()
-                if good_crypto == 0:
-                    raise
-                # this may occur at any of the three crypto operations above.
-                # some objects did validate; discard all data after it; next
-                # call will start with the bad object and error out immediately
-                self.buf = b"".join (t [good_crypto:])
-                return b"".join (t [:good_crypto])
+                if self.tolerance == TOLERANCE_RECOVER:
+                    if good_crypto == 0:
+                        raise
+                    # this may occur at any of the three crypto operations above.
+                    # some objects did validate; discard all data after it; next
+                    # call will start with the bad object and error out immediately
+                    self.buf = b"".join (t [good_crypto:])
+                    return b"".join (t [:good_crypto])
+                elif self.tolerance == TOLERANCE_RESCUE:
+                    # keep what we have so far despite the finalization issue
+                    t.append (buf)
+                    c += len (buf)
+                    break
+                else:
+                    raise RuntimeError("internal error: bad tolerance level")
 
             if not buf: ## XXX stream terminated prematurely; this should be an error
                 break