summaryrefslogtreecommitdiff
path: root/Modules/_bz2module.c
diff options
context:
space:
mode:
authorNadeem Vawda <nadeem.vawda@gmail.com>2011-04-12 23:02:42 +0200
committerNadeem Vawda <nadeem.vawda@gmail.com>2011-04-12 23:02:42 +0200
commitea4b46f9a9056de25a3e368aa458c7dd94c853bf (patch)
treebea3e5c2dd50c54d0621411f883d30b8832a80a9 /Modules/_bz2module.c
parentb30f1b41061161225968ab74801694bffea85e1f (diff)
downloadcpython-git-ea4b46f9a9056de25a3e368aa458c7dd94c853bf.tar.gz
Fix 64-bit safety issue in BZ2Compressor and BZ2Decompressor.
Diffstat (limited to 'Modules/_bz2module.c')
-rw-r--r--Modules/_bz2module.c33
1 files changed, 24 insertions, 9 deletions
diff --git a/Modules/_bz2module.c b/Modules/_bz2module.c
index 522b3e5658..d329c14626 100644
--- a/Modules/_bz2module.c
+++ b/Modules/_bz2module.c
@@ -36,6 +36,8 @@
#define RELEASE_LOCK(obj)
#endif
+#define MIN(X, Y) (((X) < (Y)) ? (X) : (Y))
+
typedef struct {
PyObject_HEAD
@@ -145,8 +147,10 @@ compress(BZ2Compressor *c, char *data, size_t len, int action)
if (result == NULL)
return NULL;
c->bzs.next_in = data;
- /* FIXME This is not 64-bit clean - avail_in is an int. */
- c->bzs.avail_in = len;
+ /* On a 64-bit system, len might not fit in avail_in (an unsigned int).
+ 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.avail_out = PyBytes_GET_SIZE(result);
for (;;) {
@@ -161,6 +165,11 @@ compress(BZ2Compressor *c, char *data, size_t len, int action)
if (catch_bz2_error(bzerror))
goto error;
+ if (c->bzs.avail_in == 0 && len > 0) {
+ c->bzs.avail_in = MIN(len, UINT_MAX);
+ len -= c->bzs.avail_in;
+ }
+
/* 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) ||
@@ -354,8 +363,10 @@ decompress(BZ2Decompressor *d, char *data, size_t len)
if (result == NULL)
return result;
d->bzs.next_in = data;
- /* FIXME This is not 64-bit clean - avail_in is an int. */
- d->bzs.avail_in = len;
+ /* On a 64-bit system, len might not fit in avail_in (an unsigned int).
+ Do decompression in chunks of no more than UINT_MAX bytes each. */
+ d->bzs.avail_in = MIN(len, UINT_MAX);
+ len -= d->bzs.avail_in;
d->bzs.next_out = PyBytes_AS_STRING(result);
d->bzs.avail_out = PyBytes_GET_SIZE(result);
for (;;) {
@@ -371,17 +382,21 @@ decompress(BZ2Decompressor *d, char *data, size_t len)
goto error;
if (bzerror == BZ_STREAM_END) {
d->eof = 1;
- if (d->bzs.avail_in > 0) { /* Save leftover input to unused_data */
+ len += d->bzs.avail_in;
+ if (len > 0) { /* Save leftover input to unused_data */
Py_CLEAR(d->unused_data);
- d->unused_data = PyBytes_FromStringAndSize(d->bzs.next_in,
- d->bzs.avail_in);
+ d->unused_data = PyBytes_FromStringAndSize(d->bzs.next_in, len);
if (d->unused_data == NULL)
goto error;
}
break;
}
- if (d->bzs.avail_in == 0)
- break;
+ if (d->bzs.avail_in == 0) {
+ if (len == 0)
+ break;
+ d->bzs.avail_in = MIN(len, UINT_MAX);
+ len -= d->bzs.avail_in;
+ }
if (d->bzs.avail_out == 0) {
if (grow_buffer(&result) < 0)
goto error;