From 24afaf18c77f7eddae5df3c561df43ce6279a39d Mon Sep 17 00:00:00 2001 From: Philipp Gesang Date: Mon, 28 Aug 2017 17:56:33 +0200 Subject: [PATCH] allow for detecting overlapping objects with tarfile --- deltatar/crypto.py | 15 +++++++++------ deltatar/tarfile.py | 31 +++++++++++++++++++++++-------- 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/deltatar/crypto.py b/deltatar/crypto.py index a381d2b..41f0cbd 100755 --- a/deltatar/crypto.py +++ b/deltatar/crypto.py @@ -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): diff --git a/deltatar/tarfile.py b/deltatar/tarfile.py index c63bb23..31e46b9 100644 --- a/deltatar/tarfile.py +++ b/deltatar/tarfile.py @@ -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 -- 1.7.1