Kaydet (Commit) 88b22193 authored tarafından Serhiy Storchaka's avatar Serhiy Storchaka

Issue #27517: LZMA compressor and decompressor no longer raise exceptions if

given empty data twice.  Patch by Benjamin Fogle.
...@@ -137,6 +137,21 @@ class CompressorDecompressorTestCase(unittest.TestCase): ...@@ -137,6 +137,21 @@ class CompressorDecompressorTestCase(unittest.TestCase):
self.assertTrue(lzd.eof) self.assertTrue(lzd.eof)
self.assertEqual(lzd.unused_data, b"") 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): def test_decompressor_chunks_maxsize(self):
lzd = LZMADecompressor() lzd = LZMADecompressor()
max_length = 100 max_length = 100
...@@ -274,6 +289,16 @@ class CompressorDecompressorTestCase(unittest.TestCase): ...@@ -274,6 +289,16 @@ class CompressorDecompressorTestCase(unittest.TestCase):
lzd = LZMADecompressor(lzma.FORMAT_RAW, filters=FILTERS_RAW_4) lzd = LZMADecompressor(lzma.FORMAT_RAW, filters=FILTERS_RAW_4)
self._test_decompressor(lzd, cdata, lzma.CHECK_NONE) 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): def test_roundtrip_chunks(self):
lzc = LZMACompressor() lzc = LZMACompressor()
cdata = [] cdata = []
...@@ -284,6 +309,19 @@ class CompressorDecompressorTestCase(unittest.TestCase): ...@@ -284,6 +309,19 @@ class CompressorDecompressorTestCase(unittest.TestCase):
lzd = LZMADecompressor() lzd = LZMADecompressor()
self._test_decompressor(lzd, cdata, lzma.CHECK_CRC64) 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. # LZMADecompressor intentionally does not handle concatenated streams.
def test_decompressor_multistream(self): def test_decompressor_multistream(self):
......
...@@ -452,6 +452,7 @@ Frederik Fix ...@@ -452,6 +452,7 @@ Frederik Fix
Tom Flanagan Tom Flanagan
Matt Fleming Matt Fleming
Hernán Martínez Foffani Hernán Martínez Foffani
Benjamin Fogle
Artem Fokin Artem Fokin
Arnaud Fontaine Arnaud Fontaine
Michael Foord Michael Foord
......
...@@ -30,6 +30,9 @@ Core and Builtins ...@@ -30,6 +30,9 @@ Core and Builtins
Library 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 #28549: Fixed segfault in curses's addch() with ncurses6.
- Issue #28449: tarfile.open() with mode "r" or "r:" now tries to open a tar - Issue #28449: tarfile.open() with mode "r" or "r:" now tries to open a tar
......
...@@ -521,6 +521,8 @@ compress(Compressor *c, uint8_t *data, size_t len, lzma_action action) ...@@ -521,6 +521,8 @@ compress(Compressor *c, uint8_t *data, size_t len, lzma_action action)
Py_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS
lzret = lzma_code(&c->lzs, action); lzret = lzma_code(&c->lzs, action);
data_size = (char *)c->lzs.next_out - PyBytes_AS_STRING(result); 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 Py_END_ALLOW_THREADS
if (catch_lzma_error(lzret)) if (catch_lzma_error(lzret))
goto error; goto error;
...@@ -896,6 +898,9 @@ decompress_buf(Decompressor *d, Py_ssize_t max_length) ...@@ -896,6 +898,9 @@ decompress_buf(Decompressor *d, Py_ssize_t max_length)
PyObject *result; PyObject *result;
lzma_stream *lzs = &d->lzs; lzma_stream *lzs = &d->lzs;
if (lzs->avail_in == 0)
return PyBytes_FromStringAndSize(NULL, 0);
if (max_length < 0 || max_length >= INITIAL_BUFFER_SIZE) if (max_length < 0 || max_length >= INITIAL_BUFFER_SIZE)
result = PyBytes_FromStringAndSize(NULL, INITIAL_BUFFER_SIZE); result = PyBytes_FromStringAndSize(NULL, INITIAL_BUFFER_SIZE);
else else
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment