Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit ecf40c1

Browse files
Issue python#27517: LZMA compressor and decompressor no longer raise exceptions if
given empty data twice. Patch by Benjamin Fogle.
2 parents 4eebf84 + 88b2219 commit ecf40c1

4 files changed

Lines changed: 47 additions & 0 deletions

File tree

Lib/test/test_lzma.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,21 @@ def test_decompressor_chunks(self):
137137
self.assertTrue(lzd.eof)
138138
self.assertEqual(lzd.unused_data, b"")
139139

140+
def test_decompressor_chunks_empty(self):
141+
lzd = LZMADecompressor()
142+
out = []
143+
for i in range(0, len(COMPRESSED_XZ), 10):
144+
self.assertFalse(lzd.eof)
145+
out.append(lzd.decompress(b''))
146+
out.append(lzd.decompress(b''))
147+
out.append(lzd.decompress(b''))
148+
out.append(lzd.decompress(COMPRESSED_XZ[i:i+10]))
149+
out = b"".join(out)
150+
self.assertEqual(out, INPUT)
151+
self.assertEqual(lzd.check, lzma.CHECK_CRC64)
152+
self.assertTrue(lzd.eof)
153+
self.assertEqual(lzd.unused_data, b"")
154+
140155
def test_decompressor_chunks_maxsize(self):
141156
lzd = LZMADecompressor()
142157
max_length = 100
@@ -274,6 +289,16 @@ def test_roundtrip_raw(self):
274289
lzd = LZMADecompressor(lzma.FORMAT_RAW, filters=FILTERS_RAW_4)
275290
self._test_decompressor(lzd, cdata, lzma.CHECK_NONE)
276291

292+
def test_roundtrip_raw_empty(self):
293+
lzc = LZMACompressor(lzma.FORMAT_RAW, filters=FILTERS_RAW_4)
294+
cdata = lzc.compress(INPUT)
295+
cdata += lzc.compress(b'')
296+
cdata += lzc.compress(b'')
297+
cdata += lzc.compress(b'')
298+
cdata += lzc.flush()
299+
lzd = LZMADecompressor(lzma.FORMAT_RAW, filters=FILTERS_RAW_4)
300+
self._test_decompressor(lzd, cdata, lzma.CHECK_NONE)
301+
277302
def test_roundtrip_chunks(self):
278303
lzc = LZMACompressor()
279304
cdata = []
@@ -284,6 +309,19 @@ def test_roundtrip_chunks(self):
284309
lzd = LZMADecompressor()
285310
self._test_decompressor(lzd, cdata, lzma.CHECK_CRC64)
286311

312+
def test_roundtrip_empty_chunks(self):
313+
lzc = LZMACompressor()
314+
cdata = []
315+
for i in range(0, len(INPUT), 10):
316+
cdata.append(lzc.compress(INPUT[i:i+10]))
317+
cdata.append(lzc.compress(b''))
318+
cdata.append(lzc.compress(b''))
319+
cdata.append(lzc.compress(b''))
320+
cdata.append(lzc.flush())
321+
cdata = b"".join(cdata)
322+
lzd = LZMADecompressor()
323+
self._test_decompressor(lzd, cdata, lzma.CHECK_CRC64)
324+
287325
# LZMADecompressor intentionally does not handle concatenated streams.
288326

289327
def test_decompressor_multistream(self):

Misc/ACKS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,7 @@ Frederik Fix
453453
Tom Flanagan
454454
Matt Fleming
455455
Hernán Martínez Foffani
456+
Benjamin Fogle
456457
Artem Fokin
457458
Arnaud Fontaine
458459
Michael Foord

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,9 @@ Core and Builtins
9999
Library
100100
-------
101101

102+
- Issue #27517: LZMA compressor and decompressor no longer raise exceptions if
103+
given empty data twice. Patch by Benjamin Fogle.
104+
102105
- Issue #28549: Fixed segfault in curses's addch() with ncurses6.
103106

104107
- Issue #28449: tarfile.open() with mode "r" or "r:" now tries to open a tar

Modules/_lzmamodule.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -521,6 +521,8 @@ compress(Compressor *c, uint8_t *data, size_t len, lzma_action action)
521521
Py_BEGIN_ALLOW_THREADS
522522
lzret = lzma_code(&c->lzs, action);
523523
data_size = (char *)c->lzs.next_out - PyBytes_AS_STRING(result);
524+
if (lzret == LZMA_BUF_ERROR && len == 0 && c->lzs.avail_out > 0)
525+
lzret = LZMA_OK; /* That wasn't a real error */
524526
Py_END_ALLOW_THREADS
525527
if (catch_lzma_error(lzret))
526528
goto error;
@@ -896,6 +898,9 @@ decompress_buf(Decompressor *d, Py_ssize_t max_length)
896898
PyObject *result;
897899
lzma_stream *lzs = &d->lzs;
898900

901+
if (lzs->avail_in == 0)
902+
return PyBytes_FromStringAndSize(NULL, 0);
903+
899904
if (max_length < 0 || max_length >= INITIAL_BUFFER_SIZE)
900905
result = PyBytes_FromStringAndSize(NULL, INITIAL_BUFFER_SIZE);
901906
else

0 commit comments

Comments
 (0)