Commit 57cb81d1 authored by Nadeem Vawda's avatar Nadeem Vawda

Issue #16828: Fix error incorrectly raised by bz2.compress('').

Initial patch by Martin Packman.
parents 407c2ac4 638fb9bb
...@@ -47,6 +47,7 @@ class BaseTest(unittest.TestCase): ...@@ -47,6 +47,7 @@ class BaseTest(unittest.TestCase):
] ]
TEXT = b''.join(TEXT_LINES) TEXT = b''.join(TEXT_LINES)
DATA = b'BZh91AY&SY.\xc8N\x18\x00\x01>_\x80\x00\x10@\x02\xff\xf0\x01\x07n\x00?\xe7\xff\xe00\x01\x99\xaa\x00\xc0\x03F\x86\x8c#&\x83F\x9a\x03\x06\xa6\xd0\xa6\x93M\x0fQ\xa7\xa8\x06\x804hh\x12$\x11\xa4i4\xf14S\xd2<Q\xb5\x0fH\xd3\xd4\xdd\xd5\x87\xbb\xf8\x94\r\x8f\xafI\x12\xe1\xc9\xf8/E\x00pu\x89\x12]\xc9\xbbDL\nQ\x0e\t1\x12\xdf\xa0\xc0\x97\xac2O9\x89\x13\x94\x0e\x1c7\x0ed\x95I\x0c\xaaJ\xa4\x18L\x10\x05#\x9c\xaf\xba\xbc/\x97\x8a#C\xc8\xe1\x8cW\xf9\xe2\xd0\xd6M\xa7\x8bXa<e\x84t\xcbL\xb3\xa7\xd9\xcd\xd1\xcb\x84.\xaf\xb3\xab\xab\xad`n}\xa0lh\tE,\x8eZ\x15\x17VH>\x88\xe5\xcd9gd6\x0b\n\xe9\x9b\xd5\x8a\x99\xf7\x08.K\x8ev\xfb\xf7xw\xbb\xdf\xa1\x92\xf1\xdd|/";\xa2\xba\x9f\xd5\xb1#A\xb6\xf6\xb3o\xc9\xc5y\\\xebO\xe7\x85\x9a\xbc\xb6f8\x952\xd5\xd7"%\x89>V,\xf7\xa6z\xe2\x9f\xa3\xdf\x11\x11"\xd6E)I\xa9\x13^\xca\xf3r\xd0\x03U\x922\xf26\xec\xb6\xed\x8b\xc3U\x13\x9d\xc5\x170\xa4\xfa^\x92\xacDF\x8a\x97\xd6\x19\xfe\xdd\xb8\xbd\x1a\x9a\x19\xa3\x80ankR\x8b\xe5\xd83]\xa9\xc6\x08\x82f\xf6\xb9"6l$\xb8j@\xc0\x8a\xb0l1..\xbak\x83ls\x15\xbc\xf4\xc1\x13\xbe\xf8E\xb8\x9d\r\xa8\x9dk\x84\xd3n\xfa\xacQ\x07\xb1%y\xaav\xb4\x08\xe0z\x1b\x16\xf5\x04\xe9\xcc\xb9\x08z\x1en7.G\xfc]\xc9\x14\xe1B@\xbb!8`' DATA = b'BZh91AY&SY.\xc8N\x18\x00\x01>_\x80\x00\x10@\x02\xff\xf0\x01\x07n\x00?\xe7\xff\xe00\x01\x99\xaa\x00\xc0\x03F\x86\x8c#&\x83F\x9a\x03\x06\xa6\xd0\xa6\x93M\x0fQ\xa7\xa8\x06\x804hh\x12$\x11\xa4i4\xf14S\xd2<Q\xb5\x0fH\xd3\xd4\xdd\xd5\x87\xbb\xf8\x94\r\x8f\xafI\x12\xe1\xc9\xf8/E\x00pu\x89\x12]\xc9\xbbDL\nQ\x0e\t1\x12\xdf\xa0\xc0\x97\xac2O9\x89\x13\x94\x0e\x1c7\x0ed\x95I\x0c\xaaJ\xa4\x18L\x10\x05#\x9c\xaf\xba\xbc/\x97\x8a#C\xc8\xe1\x8cW\xf9\xe2\xd0\xd6M\xa7\x8bXa<e\x84t\xcbL\xb3\xa7\xd9\xcd\xd1\xcb\x84.\xaf\xb3\xab\xab\xad`n}\xa0lh\tE,\x8eZ\x15\x17VH>\x88\xe5\xcd9gd6\x0b\n\xe9\x9b\xd5\x8a\x99\xf7\x08.K\x8ev\xfb\xf7xw\xbb\xdf\xa1\x92\xf1\xdd|/";\xa2\xba\x9f\xd5\xb1#A\xb6\xf6\xb3o\xc9\xc5y\\\xebO\xe7\x85\x9a\xbc\xb6f8\x952\xd5\xd7"%\x89>V,\xf7\xa6z\xe2\x9f\xa3\xdf\x11\x11"\xd6E)I\xa9\x13^\xca\xf3r\xd0\x03U\x922\xf26\xec\xb6\xed\x8b\xc3U\x13\x9d\xc5\x170\xa4\xfa^\x92\xacDF\x8a\x97\xd6\x19\xfe\xdd\xb8\xbd\x1a\x9a\x19\xa3\x80ankR\x8b\xe5\xd83]\xa9\xc6\x08\x82f\xf6\xb9"6l$\xb8j@\xc0\x8a\xb0l1..\xbak\x83ls\x15\xbc\xf4\xc1\x13\xbe\xf8E\xb8\x9d\r\xa8\x9dk\x84\xd3n\xfa\xacQ\x07\xb1%y\xaav\xb4\x08\xe0z\x1b\x16\xf5\x04\xe9\xcc\xb9\x08z\x1en7.G\xfc]\xc9\x14\xe1B@\xbb!8`'
EMPTY_DATA = b'BZh9\x17rE8P\x90\x00\x00\x00\x00'
def setUp(self): def setUp(self):
self.filename = TESTFN self.filename = TESTFN
...@@ -584,6 +585,12 @@ class BZ2CompressorTest(BaseTest): ...@@ -584,6 +585,12 @@ class BZ2CompressorTest(BaseTest):
data += bz2c.flush() data += bz2c.flush()
self.assertEqual(self.decompress(data), self.TEXT) self.assertEqual(self.decompress(data), self.TEXT)
def testCompressEmptyString(self):
bz2c = BZ2Compressor()
data = bz2c.compress(b'')
data += bz2c.flush()
self.assertEqual(data, self.EMPTY_DATA)
def testCompressChunks10(self): def testCompressChunks10(self):
bz2c = BZ2Compressor() bz2c = BZ2Compressor()
n = 0 n = 0
...@@ -671,6 +678,10 @@ class CompressDecompressTest(BaseTest): ...@@ -671,6 +678,10 @@ class CompressDecompressTest(BaseTest):
data = bz2.compress(self.TEXT) data = bz2.compress(self.TEXT)
self.assertEqual(self.decompress(data), self.TEXT) self.assertEqual(self.decompress(data), self.TEXT)
def testCompressEmptyString(self):
text = bz2.compress(b'')
self.assertEqual(text, self.EMPTY_DATA)
def testDecompress(self): def testDecompress(self):
text = bz2.decompress(self.DATA) text = bz2.decompress(self.DATA)
self.assertEqual(text, self.TEXT) self.assertEqual(text, self.TEXT)
...@@ -679,6 +690,10 @@ class CompressDecompressTest(BaseTest): ...@@ -679,6 +690,10 @@ class CompressDecompressTest(BaseTest):
text = bz2.decompress(b"") text = bz2.decompress(b"")
self.assertEqual(text, b"") self.assertEqual(text, b"")
def testDecompressToEmptyString(self):
text = bz2.decompress(self.EMPTY_DATA)
self.assertEqual(text, b'')
def testDecompressIncomplete(self): def testDecompressIncomplete(self):
self.assertRaises(ValueError, bz2.decompress, self.DATA[:-10]) self.assertRaises(ValueError, bz2.decompress, self.DATA[:-10])
......
...@@ -884,6 +884,7 @@ Michael Otteneder ...@@ -884,6 +884,7 @@ Michael Otteneder
R. M. Oudkerk R. M. Oudkerk
Russel Owen Russel Owen
Joonas Paalasmaa Joonas Paalasmaa
Martin Packman
Shriphani Palakodety Shriphani Palakodety
Ondrej Palkovsky Ondrej Palkovsky
Mike Pall Mike Pall
......
...@@ -123,6 +123,9 @@ Core and Builtins ...@@ -123,6 +123,9 @@ Core and Builtins
Library Library
------- -------
- Issue #16828: Fix error incorrectly raised by bz2.compress(''). Initial patch
by Martin Packman.
- Issue #16541: tk_setPalette() now works with keyword arguments. - Issue #16541: tk_setPalette() now works with keyword arguments.
- Issue #16820: In configparser, `parser.popitem()` no longer raises ValueError. - Issue #16820: In configparser, `parser.popitem()` no longer raises ValueError.
......
...@@ -145,34 +145,24 @@ compress(BZ2Compressor *c, char *data, size_t len, int action) ...@@ -145,34 +145,24 @@ compress(BZ2Compressor *c, char *data, size_t len, int action)
result = PyBytes_FromStringAndSize(NULL, SMALLCHUNK); result = PyBytes_FromStringAndSize(NULL, SMALLCHUNK);
if (result == NULL) if (result == NULL)
return NULL; return NULL;
c->bzs.next_in = data; c->bzs.next_in = data;
/* On a 64-bit system, len might not fit in avail_in (an unsigned int). c->bzs.avail_in = 0;
Do compression in chunks of no more than UINT_MAX bytes each. */
c->bzs.avail_in = MIN(len, UINT_MAX);
len -= c->bzs.avail_in;
c->bzs.next_out = PyBytes_AS_STRING(result); c->bzs.next_out = PyBytes_AS_STRING(result);
c->bzs.avail_out = PyBytes_GET_SIZE(result); c->bzs.avail_out = PyBytes_GET_SIZE(result);
for (;;) { for (;;) {
char *this_out; char *this_out;
int bzerror; int bzerror;
Py_BEGIN_ALLOW_THREADS /* On a 64-bit system, len might not fit in avail_in (an unsigned int).
this_out = c->bzs.next_out; Do compression in chunks of no more than UINT_MAX bytes each. */
bzerror = BZ2_bzCompress(&c->bzs, action);
data_size += c->bzs.next_out - this_out;
Py_END_ALLOW_THREADS
if (catch_bz2_error(bzerror))
goto error;
if (c->bzs.avail_in == 0 && len > 0) { if (c->bzs.avail_in == 0 && len > 0) {
c->bzs.avail_in = MIN(len, UINT_MAX); c->bzs.avail_in = MIN(len, UINT_MAX);
len -= c->bzs.avail_in; len -= c->bzs.avail_in;
} }
/* In regular compression mode, stop when input data is exhausted. /* In regular compression mode, stop when input data is exhausted. */
In flushing mode, stop when all buffered data has been flushed. */ if (action == BZ_RUN && c->bzs.avail_in == 0)
if ((action == BZ_RUN && c->bzs.avail_in == 0) ||
(action == BZ_FINISH && bzerror == BZ_STREAM_END))
break; break;
if (c->bzs.avail_out == 0) { if (c->bzs.avail_out == 0) {
...@@ -185,6 +175,18 @@ compress(BZ2Compressor *c, char *data, size_t len, int action) ...@@ -185,6 +175,18 @@ compress(BZ2Compressor *c, char *data, size_t len, int action)
} }
c->bzs.avail_out = MIN(buffer_left, UINT_MAX); c->bzs.avail_out = MIN(buffer_left, UINT_MAX);
} }
Py_BEGIN_ALLOW_THREADS
this_out = c->bzs.next_out;
bzerror = BZ2_bzCompress(&c->bzs, action);
data_size += c->bzs.next_out - this_out;
Py_END_ALLOW_THREADS
if (catch_bz2_error(bzerror))
goto error;
/* In flushing mode, stop when all buffered data has been flushed. */
if (action == BZ_FINISH && bzerror == BZ_STREAM_END)
break;
} }
if (data_size != PyBytes_GET_SIZE(result)) if (data_size != PyBytes_GET_SIZE(result))
if (_PyBytes_Resize(&result, data_size) < 0) if (_PyBytes_Resize(&result, data_size) < 0)
......
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