Explorar el Código

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
TW hace 8 años
padre
commit
5efda261b3
Se han modificado 3 ficheros con 20 adiciones y 6 borrados
  1. 12 4
      borg/compress.pyx
  2. 7 1
      borg/helpers.py
  3. 1 1
      borg/testsuite/archiver.py

+ 12 - 4
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 = {

+ 7 - 1
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':

+ 1 - 1
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)