]> granicus.if.org Git - python/commitdiff
Issue #27517: LZMA compressor and decompressor no longer raise exceptions if
authorSerhiy Storchaka <storchaka@gmail.com>
Mon, 31 Oct 2016 06:30:09 +0000 (08:30 +0200)
committerSerhiy Storchaka <storchaka@gmail.com>
Mon, 31 Oct 2016 06:30:09 +0000 (08:30 +0200)
given empty data twice.  Patch by Benjamin Fogle.

Lib/test/test_lzma.py
Misc/ACKS
Misc/NEWS
Modules/_lzmamodule.c

index 16e89d5a9e97941dc5ce97cbd8bba79d8a07dacc..b69da065e1dfe64ef489512889ceea6174c1ed0f 100644 (file)
@@ -136,6 +136,21 @@ class CompressorDecompressorTestCase(unittest.TestCase):
         self.assertTrue(lzd.eof)
         self.assertEqual(lzd.unused_data, b"")
 
+    def test_decompressor_chunks_empty(self):
+        lzd = LZMADecompressor()
+        out = []
+        for i in range(0, len(COMPRESSED_XZ), 10):
+            self.assertFalse(lzd.eof)
+            out.append(lzd.decompress(b''))
+            out.append(lzd.decompress(b''))
+            out.append(lzd.decompress(b''))
+            out.append(lzd.decompress(COMPRESSED_XZ[i:i+10]))
+        out = b"".join(out)
+        self.assertEqual(out, INPUT)
+        self.assertEqual(lzd.check, lzma.CHECK_CRC64)
+        self.assertTrue(lzd.eof)
+        self.assertEqual(lzd.unused_data, b"")
+
     def test_decompressor_chunks_maxsize(self):
         lzd = LZMADecompressor()
         max_length = 100
@@ -273,6 +288,16 @@ class CompressorDecompressorTestCase(unittest.TestCase):
         lzd = LZMADecompressor(lzma.FORMAT_RAW, filters=FILTERS_RAW_4)
         self._test_decompressor(lzd, cdata, lzma.CHECK_NONE)
 
+    def test_roundtrip_raw_empty(self):
+        lzc = LZMACompressor(lzma.FORMAT_RAW, filters=FILTERS_RAW_4)
+        cdata = lzc.compress(INPUT)
+        cdata += lzc.compress(b'')
+        cdata += lzc.compress(b'')
+        cdata += lzc.compress(b'')
+        cdata += lzc.flush()
+        lzd = LZMADecompressor(lzma.FORMAT_RAW, filters=FILTERS_RAW_4)
+        self._test_decompressor(lzd, cdata, lzma.CHECK_NONE)
+
     def test_roundtrip_chunks(self):
         lzc = LZMACompressor()
         cdata = []
@@ -283,6 +308,19 @@ class CompressorDecompressorTestCase(unittest.TestCase):
         lzd = LZMADecompressor()
         self._test_decompressor(lzd, cdata, lzma.CHECK_CRC64)
 
+    def test_roundtrip_empty_chunks(self):
+        lzc = LZMACompressor()
+        cdata = []
+        for i in range(0, len(INPUT), 10):
+            cdata.append(lzc.compress(INPUT[i:i+10]))
+            cdata.append(lzc.compress(b''))
+            cdata.append(lzc.compress(b''))
+            cdata.append(lzc.compress(b''))
+        cdata.append(lzc.flush())
+        cdata = b"".join(cdata)
+        lzd = LZMADecompressor()
+        self._test_decompressor(lzd, cdata, lzma.CHECK_CRC64)
+
     # LZMADecompressor intentionally does not handle concatenated streams.
 
     def test_decompressor_multistream(self):
index 2ba9ea14cc7916d20b4209b29b3fc96005ae9949..46d6adf41340e394e50237e4ef12f7ca4ee0d4d4 100644 (file)
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -446,6 +446,7 @@ Frederik Fix
 Tom Flanagan
 Matt Fleming
 Hernán Martínez Foffani
+Benjamin Fogle
 Artem Fokin
 Arnaud Fontaine
 Michael Foord
index d7f3d28264a463893db45fe79d22d8d5e69b5d50..808501b3fccbc96ad08e77552ffcd6b67b979313 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -113,6 +113,9 @@ Core and Builtins
 Library
 -------
 
+- Issue #27517: LZMA compressor and decompressor no longer raise exceptions if
+  given empty data twice.  Patch by Benjamin Fogle.
+
 - Issue #28549: Fixed segfault in curses's addch() with ncurses6.
 
 - Issue #28449: tarfile.open() with mode "r" or "r:" now tries to open a tar
index 74c301d47ad4f4eeaee7463c1d25b652ac0b2ce5..e7b1ed9fb2bce7a178dadeb0476e2c0232a8e4e8 100644 (file)
@@ -527,6 +527,8 @@ compress(Compressor *c, uint8_t *data, size_t len, lzma_action action)
         Py_BEGIN_ALLOW_THREADS
         lzret = lzma_code(&c->lzs, action);
         data_size = (char *)c->lzs.next_out - PyBytes_AS_STRING(result);
+        if (lzret == LZMA_BUF_ERROR && len == 0 && c->lzs.avail_out > 0)
+            lzret = LZMA_OK; /* That wasn't a real error */
         Py_END_ALLOW_THREADS
         if (catch_lzma_error(lzret))
             goto error;
@@ -906,6 +908,9 @@ decompress_buf(Decompressor *d, Py_ssize_t max_length)
     PyObject *result;
     lzma_stream *lzs = &d->lzs;
 
+    if (lzs->avail_in == 0)
+        return PyBytes_FromStringAndSize(NULL, 0);
+
     if (max_length < 0 || max_length >= INITIAL_BUFFER_SIZE)
         result = PyBytes_FromStringAndSize(NULL, INITIAL_BUFFER_SIZE);
     else