From 5efda261b35be0d58b3770897cd9d385987d8c4b Mon Sep 17 00:00:00 2001 From: TW Date: Sat, 4 Mar 2017 00:01:02 +0100 Subject: [PATCH] Fix compression exceptions (#2224) * trigger bug in --verify-data, see #2221 * raise decompression errors as DecompressionError, fixes #2221 this is a subclass of IntegrityError, so borg check --verify-data works correctly if the decompressor stumbles over corrupted data before the plaintext gets verified (in a unencrypted repository, otherwise the MAC check would fail first). * fixup: fix exception docstring, add placeholder, change wording --- borg/compress.pyx | 16 ++++++++++++---- borg/helpers.py | 8 +++++++- borg/testsuite/archiver.py | 2 +- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/borg/compress.pyx b/borg/compress.pyx index f0dd0b1b3..61b1300e1 100644 --- a/borg/compress.pyx +++ b/borg/compress.pyx @@ -4,7 +4,9 @@ try: except ImportError: lzma = None -from .helpers import Buffer +from .helpers import Buffer, DecompressionError + +API_VERSION = '1.0_01' cdef extern from "lz4.h": int LZ4_compress_limitedOutput(const char* source, char* dest, int inputSize, int maxOutputSize) nogil @@ -110,7 +112,7 @@ class LZ4(CompressorBase): break if osize > 2 ** 30: # this is insane, get out of here - raise Exception('lz4 decompress failed') + raise DecompressionError('lz4 decompress failed') # likely the buffer was too small, get a bigger one: osize = int(1.5 * osize) return dest[:rsize] @@ -136,7 +138,10 @@ class LZMA(CompressorBase): def decompress(self, data): data = super().decompress(data) - return lzma.decompress(data) + try: + return lzma.decompress(data) + except lzma.LZMAError as e: + raise DecompressionError(str(e)) from None class ZLIB(CompressorBase): @@ -165,7 +170,10 @@ class ZLIB(CompressorBase): def decompress(self, data): # note: for compatibility no super call, do not strip ID bytes - return zlib.decompress(data) + try: + return zlib.decompress(data) + except zlib.error as e: + raise DecompressionError(str(e)) from None COMPRESSOR_TABLE = { diff --git a/borg/helpers.py b/borg/helpers.py index 36cc1ad0a..388a1c536 100644 --- a/borg/helpers.py +++ b/borg/helpers.py @@ -74,6 +74,10 @@ class IntegrityError(ErrorWithTraceback): """Data integrity error: {}""" +class DecompressionError(IntegrityError): + """Decompression error: {}""" + + class ExtensionModuleError(Error): """The Borg binary extension modules do not seem to be properly installed""" @@ -87,11 +91,13 @@ class PlaceholderError(Error): def check_extension_modules(): - from . import platform + from . import platform, compress if hashindex.API_VERSION != '1.0_01': raise ExtensionModuleError if chunker.API_VERSION != '1.0_01': raise ExtensionModuleError + if compress.API_VERSION != '1.0_01': + raise ExtensionModuleError if crypto.API_VERSION != '1.0_01': raise ExtensionModuleError if platform.API_VERSION != '1.0_01': diff --git a/borg/testsuite/archiver.py b/borg/testsuite/archiver.py index 53b3a1bc6..f688ba182 100644 --- a/borg/testsuite/archiver.py +++ b/borg/testsuite/archiver.py @@ -245,7 +245,7 @@ class ArchiverTestCaseBase(BaseTestCase): return output def create_src_archive(self, name): - self.cmd('create', self.repository_location + '::' + name, src_dir) + self.cmd('create', '--compression=lz4', self.repository_location + '::' + name, src_dir) def open_archive(self, name): repository = Repository(self.repository_path, exclusive=True)