From: Philipp Gesang Date: Thu, 31 Aug 2017 09:41:50 +0000 (+0200) Subject: add tests for truncated files X-Git-Tag: v2.2~7^2~30 X-Git-Url: http://developer.intra2net.com/git/?p=python-delta-tar;a=commitdiff_plain;h=37ccf5bcf414845774d72444cd216352a68b8898 add tests for truncated files --- diff --git a/deltatar/crypto.py b/deltatar/crypto.py index 676fa18..e19894f 100755 --- a/deltatar/crypto.py +++ b/deltatar/crypto.py @@ -635,6 +635,7 @@ def try_decrypt (ifd, off, hdr, secret, ofd=-1): try: os.lseek (ifd, pos, os.SEEK_SET) + pt = b"" while ctleft > 0: cnksiz = min (ctleft, PDTCRYPT_BLOCKSIZE) cnk = os.read (ifd, cnksiz) diff --git a/runtests.py b/runtests.py index 457bcb0..d98a10f 100755 --- a/runtests.py +++ b/runtests.py @@ -35,6 +35,9 @@ from testing.test_recover import \ , RecoverCorruptHeaderGZMultiTest \ , RecoverCorruptHeaderGZAESSingleTest \ , RecoverCorruptHeaderGZAESMultiTest \ + , RecoverCorruptTruncateTest \ + , RecoverCorruptTruncateGZTest \ + , RecoverCorruptTruncateGZAESTest \ , RescueCorruptHeaderCTSizeGZAESTest \ , RecoverCorruptEntireHeaderSingleTest \ , RecoverCorruptEntireHeaderMultiTest \ @@ -56,6 +59,9 @@ from testing.test_recover import \ , RecoverCorruptHoleTest \ , RecoverCorruptHoleGZTest \ , RecoverCorruptHoleGZAESTest \ + , RescueCorruptTruncateTest \ + , RescueCorruptTruncateGZTest \ + , RescueCorruptTruncateGZAESTest \ , RescueCorruptHoleTest \ , RescueCorruptHoleGZTest \ , RescueCorruptHoleGZAESTest \ @@ -65,6 +71,9 @@ from testing.test_recover import \ , GenIndexIntactMultiTest \ , GenIndexIntactMultiGZTest \ , GenIndexIntactMultiGZAESTest \ + , GenIndexCorruptTruncateTest \ + , GenIndexCorruptTruncateGZTest \ + , GenIndexCorruptTruncateGZAESTest \ , GenIndexCorruptHoleTest \ , GenIndexCorruptHoleGZTest \ , GenIndexCorruptHoleGZAESTest \ @@ -119,6 +128,9 @@ if __name__ == "__main__": , RecoverCorruptHeaderGZMultiTest , RecoverCorruptHeaderGZAESSingleTest , RecoverCorruptHeaderGZAESMultiTest + , RecoverCorruptTruncateTest + , RecoverCorruptTruncateGZTest + , RecoverCorruptTruncateGZAESTest , RescueCorruptHeaderCTSizeGZAESTest , RecoverCorruptEntireHeaderSingleTest , RecoverCorruptEntireHeaderMultiTest @@ -139,6 +151,9 @@ if __name__ == "__main__": , RecoverCorruptHoleTest , RecoverCorruptHoleGZTest , RecoverCorruptHoleGZAESTest + , RescueCorruptTruncateTest + , RescueCorruptTruncateGZTest + , RescueCorruptTruncateGZAESTest , RescueCorruptHoleTest , RescueCorruptHoleGZTest , RescueCorruptHoleGZAESTest @@ -148,6 +163,9 @@ if __name__ == "__main__": , GenIndexIntactMultiTest , GenIndexIntactMultiGZTest , GenIndexIntactMultiGZAESTest + , GenIndexCorruptTruncateTest + , GenIndexCorruptTruncateGZTest + , GenIndexCorruptTruncateGZAESTest , GenIndexCorruptHoleTest , GenIndexCorruptHoleGZTest , GenIndexCorruptHoleGZAESTest diff --git a/testing/test_recover.py b/testing/test_recover.py index a8ebc55..9edea9d 100644 --- a/testing/test_recover.py +++ b/testing/test_recover.py @@ -16,6 +16,12 @@ communicated upward by throwing. compressed data, the two byte magic is altered, for uncompressed archives, the tar header checksum field. + - corrupt_truncate (): + Drop the file’s content after two thirds, causing extraction of later + objects to fail. Since the operation preserves the offsets of objects + before the cutoff, this yields the same results regardless of whether + restore or rescue mode is used. + - corrupt_ctsize (): Modify the *ctsize* field of a PDTCRYPT header. The goal is to have decryption continue past the end of the object, causing data @@ -173,6 +179,17 @@ def corrupt_header (_, fname, compress, encrypt): flip_bits (fname, 100 + 8 + 8 + 8 + 12 + 12 + 1) +def corrupt_truncate (_, fname, _compress, _encrypt): + """ + Shorten file by one third. + """ + fd = os.open (fname, os.O_WRONLY) + size = os.lseek (fd, 0, os.SEEK_END) + os.ftruncate (fd, 2 * size // 3) + os.fsync (fd) + os.close (fd) + + def corrupt_ctsize (_, fname, compress, encrypt): """ Blow up the size of an object so as to cause its apparent payload to leak @@ -701,6 +718,28 @@ class RecoverCorruptHeaderGZAESMultiTest (RecoverCorruptHeaderGZAESTestBase): VOLUMES = 3 +class RecoverCorruptTruncateTestBase (RecoverTest): + COMPRESSION = None + PASSWORD = None + FAILURES = 0 + CORRUPT = corrupt_truncate + MISMATCHES = 0 + +class RecoverCorruptTruncateTest (RecoverCorruptTruncateTestBase): + pass + +class RecoverCorruptTruncateGZTest (RecoverCorruptTruncateTestBase): + """Two files that failed missing.""" + COMPRESSION = "#gz" + FAILURES = 2 + +class RecoverCorruptTruncateGZAESTest (RecoverCorruptTruncateTestBase): + """Two files that failed missing.""" + COMPRESSION = "#gz" + PASSWORD = TEST_PASSWORD + FAILURES = 2 + + class RecoverCorruptEntireHeaderTestBase (RecoverTest): COMPRESSION = None PASSWORD = None @@ -850,6 +889,28 @@ class RecoverCorruptHoleGZAESTest (RecoverCorruptHoleBaseTest): # rescue ############################################################################### +class RescueCorruptTruncateTestBase (RescueTest): + COMPRESSION = None + PASSWORD = None + FAILURES = 0 + CORRUPT = corrupt_truncate + MISMATCHES = 0 + +class RescueCorruptTruncateTest (RescueCorruptTruncateTestBase): + pass + +class RescueCorruptTruncateGZTest (RescueCorruptTruncateTestBase): + """Two files that failed missing.""" + COMPRESSION = "#gz" + MISSING = 2 + +class RescueCorruptTruncateGZAESTest (RescueCorruptTruncateTestBase): + """Two files missing but didn’t fail on account of their absence.""" + COMPRESSION = "#gz" + PASSWORD = TEST_PASSWORD + MISSING = 2 + + @unittest.skipIf(sys.version_info < (3, 4), "requires recent os library") class RescueCorruptHoleBaseTest (RescueTest): """ @@ -956,6 +1017,27 @@ class GenIndexIntactMultiGZAESTest (GenIndexIntactBaseTest): MISSING = 2 +class GenIndexCorruptTruncateBaseTest (GenIndexTest): + """ + Recreate index from file that lacks the latter portion. + """ + COMPRESSION = None + PASSWORD = None + FAILURES = 0 + CORRUPT = corrupt_truncate + MISSING = 2 + +class GenIndexCorruptTruncateTest (GenIndexCorruptTruncateBaseTest): + pass + +class GenIndexCorruptTruncateGZTest (GenIndexCorruptTruncateBaseTest): + COMPRESSION = "#gz" + +class GenIndexCorruptTruncateGZAESTest (GenIndexCorruptTruncateBaseTest): + COMPRESSION = "#gz" + PASSWORD = TEST_PASSWORD + + class GenIndexCorruptHoleBaseTest (GenIndexTest): """ Recreate index from file with hole. @@ -980,7 +1062,6 @@ class GenIndexCorruptHoleGZAESTest (GenIndexCorruptHoleBaseTest): MISSING = 2 - class GenIndexCorruptEntireHeaderBaseTest (GenIndexTest): """ Recreate index from file with hole.