diff -r 2f0716009132 Lib/test/test_lzma.py --- a/Lib/test/test_lzma.py Tue Jul 12 18:24:25 2016 -0400 +++ b/Lib/test/test_lzma.py Thu Jul 14 20:41:02 2016 -0400 @@ -136,6 +136,21 @@ 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 @@ -276,6 +291,19 @@ 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): diff -r 2f0716009132 Modules/_lzmamodule.c --- a/Modules/_lzmamodule.c Tue Jul 12 18:24:25 2016 -0400 +++ b/Modules/_lzmamodule.c Thu Jul 14 20:41:02 2016 -0400 @@ -514,6 +514,10 @@ Py_ssize_t data_size = 0; PyObject *result; + /* Prevent erroneous LZMA_BUF_ERROR from occurring */ + if (len == 0 && action == LZMA_RUN && c->lzs.total_out > 0) + return PyBytes_FromStringAndSize(NULL, 0); + result = PyBytes_FromStringAndSize(NULL, INITIAL_BUFFER_SIZE); if (result == NULL) return NULL; @@ -902,6 +906,9 @@ 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