summaryrefslogtreecommitdiff
path: root/Modules/zlibmodule.c
diff options
context:
space:
mode:
Diffstat (limited to 'Modules/zlibmodule.c')
-rw-r--r--Modules/zlibmodule.c293
1 files changed, 185 insertions, 108 deletions
diff --git a/Modules/zlibmodule.c b/Modules/zlibmodule.c
index e718795fa7..1b65eb0be7 100644
--- a/Modules/zlibmodule.c
+++ b/Modules/zlibmodule.c
@@ -8,6 +8,7 @@
#include "structmember.h"
#include "zlib.h"
+
#ifdef WITH_THREAD
#include "pythread.h"
#define ENTER_ZLIB(obj) \
@@ -132,10 +133,30 @@ newcompobject(PyTypeObject *type)
}
#ifdef WITH_THREAD
self->lock = PyThread_allocate_lock();
+ if (self->lock == NULL) {
+ PyErr_SetString(PyExc_MemoryError, "Unable to allocate lock");
+ return NULL;
+ }
#endif
return self;
}
+static void*
+PyZlib_Malloc(voidpf ctx, uInt items, uInt size)
+{
+ if (items > (size_t)PY_SSIZE_T_MAX / size)
+ return NULL;
+ /* PyMem_Malloc() cannot be used: the GIL is not held when
+ inflate() and deflate() are called */
+ return PyMem_RawMalloc(items * size);
+}
+
+static void
+PyZlib_Free(voidpf ctx, void *ptr)
+{
+ PyMem_RawFree(ptr);
+}
+
PyDoc_STRVAR(compress__doc__,
"compress(string[, level]) -- Returned compressed string.\n"
"\n"
@@ -161,11 +182,11 @@ PyZlib_compress(PyObject *self, PyObject *args)
goto error;
}
input = pinput.buf;
- length = pinput.len;
+ length = (unsigned int)pinput.len;
zst.avail_out = length + length/1000 + 12 + 1;
- output = (Byte*)malloc(zst.avail_out);
+ output = (Byte*)PyMem_Malloc(zst.avail_out);
if (output == NULL) {
PyErr_SetString(PyExc_MemoryError,
"Can't allocate memory to compress data");
@@ -175,8 +196,9 @@ PyZlib_compress(PyObject *self, PyObject *args)
/* Past the point of no return. From here on out, we need to make sure
we clean up mallocs & INCREFs. */
- zst.zalloc = (alloc_func)NULL;
- zst.zfree = (free_func)Z_NULL;
+ zst.opaque = NULL;
+ zst.zalloc = PyZlib_Malloc;
+ zst.zfree = PyZlib_Free;
zst.next_out = (Byte *)output;
zst.next_in = (Byte *)input;
zst.avail_in = length;
@@ -218,7 +240,7 @@ PyZlib_compress(PyObject *self, PyObject *args)
error:
PyBuffer_Release(&pinput);
- free(output);
+ PyMem_Free(output);
return ReturnVal;
}
@@ -251,7 +273,7 @@ PyZlib_decompress(PyObject *self, PyObject *args)
goto error;
}
input = pinput.buf;
- length = pinput.len;
+ length = (unsigned int)pinput.len;
if (r_strlen <= 0)
r_strlen = 1;
@@ -262,8 +284,9 @@ PyZlib_decompress(PyObject *self, PyObject *args)
if (!(result_str = PyBytes_FromStringAndSize(NULL, r_strlen)))
goto error;
- zst.zalloc = (alloc_func)NULL;
- zst.zfree = (free_func)Z_NULL;
+ zst.opaque = NULL;
+ zst.zalloc = PyZlib_Malloc;
+ zst.zfree = PyZlib_Free;
zst.next_out = (Byte *)PyBytes_AS_STRING(result_str);
zst.next_in = (Byte *)input;
err = inflateInit2(&zst, wsize);
@@ -356,8 +379,9 @@ PyZlib_compressobj(PyObject *selfptr, PyObject *args, PyObject *kwargs)
self = newcompobject(&Comptype);
if (self==NULL)
goto error;
- self->zst.zalloc = (alloc_func)NULL;
- self->zst.zfree = (free_func)Z_NULL;
+ self->zst.opaque = NULL;
+ self->zst.zalloc = PyZlib_Malloc;
+ self->zst.zfree = PyZlib_Free;
self->zst.next_in = NULL;
self->zst.avail_in = 0;
err = deflateInit2(&self->zst, level, method, wbits, memLevel, strategy);
@@ -420,8 +444,9 @@ PyZlib_decompressobj(PyObject *selfptr, PyObject *args, PyObject *kwargs)
self = newcompobject(&Decomptype);
if (self == NULL)
return(NULL);
- self->zst.zalloc = (alloc_func)NULL;
- self->zst.zfree = (free_func)Z_NULL;
+ self->zst.opaque = NULL;
+ self->zst.zalloc = PyZlib_Malloc;
+ self->zst.zfree = PyZlib_Free;
self->zst.next_in = NULL;
self->zst.avail_in = 0;
if (zdict != NULL) {
@@ -525,8 +550,7 @@ PyZlib_objcompress(compobject *self, PyObject *args)
so extend the output buffer and try again */
while (err == Z_OK && self->zst.avail_out == 0) {
if (_PyBytes_Resize(&RetVal, length << 1) < 0) {
- Py_DECREF(RetVal);
- RetVal = NULL;
+ Py_CLEAR(RetVal);
goto error;
}
self->zst.next_out =
@@ -550,8 +574,7 @@ PyZlib_objcompress(compobject *self, PyObject *args)
goto error;
}
if (_PyBytes_Resize(&RetVal, self->zst.total_out - start_total_out) < 0) {
- Py_DECREF(RetVal);
- RetVal = NULL;
+ Py_CLEAR(RetVal);
}
error:
@@ -573,7 +596,7 @@ save_unconsumed_input(compobject *self, int err)
Py_ssize_t old_size = PyBytes_GET_SIZE(self->unused_data);
Py_ssize_t new_size;
PyObject *new_data;
- if (self->zst.avail_in > PY_SSIZE_T_MAX - old_size) {
+ if ((Py_ssize_t)self->zst.avail_in > PY_SSIZE_T_MAX - old_size) {
PyErr_NoMemory();
return -1;
}
@@ -604,87 +627,136 @@ save_unconsumed_input(compobject *self, int err)
return 0;
}
-PyDoc_STRVAR(decomp_decompress__doc__,
-"decompress(data, max_length) -- Return a string containing the decompressed\n"
-"version of the data.\n"
+/*[clinic]
+
+module zlib
+
+zlib.decompress
+
+ data: Py_buffer
+ The binary data to decompress.
+ max_length: int = 0
+ The maximum allowable length of the decompressed data.
+ Unconsumed input data will be stored in
+ the unconsumed_tail attribute.
+ /
+
+Return a string containing the decompressed version of the data.
+
+After calling this function, some of the input data may still be stored in
+internal buffers for later processing.
+Call the flush() method to clear these buffers.
+[clinic]*/
+
+PyDoc_STRVAR(zlib_decompress__doc__,
+"Return a string containing the decompressed version of the data.\n"
+"\n"
+"zlib.decompress(data, max_length=0)\n"
+" data\n"
+" The binary data to decompress.\n"
+" max_length\n"
+" The maximum allowable length of the decompressed data.\n"
+" Unconsumed input data will be stored in\n"
+" the unconsumed_tail attribute.\n"
"\n"
"After calling this function, some of the input data may still be stored in\n"
"internal buffers for later processing.\n"
-"Call the flush() method to clear these buffers.\n"
-"If the max_length parameter is specified then the return value will be\n"
-"no longer than max_length. Unconsumed input data will be stored in\n"
-"the unconsumed_tail attribute.");
+"Call the flush() method to clear these buffers.");
+
+#define ZLIB_DECOMPRESS_METHODDEF \
+ {"decompress", (PyCFunction)zlib_decompress, METH_VARARGS, zlib_decompress__doc__},
+
+static PyObject *
+zlib_decompress_impl(PyObject *self, Py_buffer *data, int max_length);
+
+static PyObject *
+zlib_decompress(PyObject *self, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ Py_buffer data;
+ int max_length = 0;
+
+ if (!PyArg_ParseTuple(args,
+ "y*|i:decompress",
+ &data, &max_length))
+ goto exit;
+ return_value = zlib_decompress_impl(self, &data, max_length);
+
+exit:
+ /* Cleanup for data */
+ PyBuffer_Release(&data);
+
+ return return_value;
+}
static PyObject *
-PyZlib_objdecompress(compobject *self, PyObject *args)
+zlib_decompress_impl(PyObject *self, Py_buffer *data, int max_length)
+/*[clinic checksum: 168d093d400739dde947cca1f4fb0f9d51cdc2c9]*/
{
- int err, max_length = 0;
+ compobject *zself = (compobject *)self;
+ int err;
unsigned int inplen;
Py_ssize_t old_length, length = DEFAULTALLOC;
PyObject *RetVal = NULL;
- Py_buffer pinput;
Byte *input;
unsigned long start_total_out;
- if (!PyArg_ParseTuple(args, "y*|i:decompress", &pinput,
- &max_length))
- return NULL;
- if (pinput.len > UINT_MAX) {
+ if (data->len > UINT_MAX) {
PyErr_SetString(PyExc_OverflowError,
"Size does not fit in an unsigned int");
- goto error_outer;
+ return NULL;
}
- input = pinput.buf;
- inplen = pinput.len;
+ input = data->buf;
+ inplen = data->len;
if (max_length < 0) {
PyErr_SetString(PyExc_ValueError,
"max_length must be greater than zero");
- goto error_outer;
+ return NULL;
}
/* limit amount of data allocated to max_length */
if (max_length && length > max_length)
length = max_length;
if (!(RetVal = PyBytes_FromStringAndSize(NULL, length)))
- goto error_outer;
+ return NULL;
- ENTER_ZLIB(self);
+ ENTER_ZLIB(zself);
- start_total_out = self->zst.total_out;
- self->zst.avail_in = inplen;
- self->zst.next_in = input;
- self->zst.avail_out = length;
- self->zst.next_out = (unsigned char *)PyBytes_AS_STRING(RetVal);
+ start_total_out = zself->zst.total_out;
+ zself->zst.avail_in = inplen;
+ zself->zst.next_in = input;
+ zself->zst.avail_out = length;
+ zself->zst.next_out = (unsigned char *)PyBytes_AS_STRING(RetVal);
Py_BEGIN_ALLOW_THREADS
- err = inflate(&(self->zst), Z_SYNC_FLUSH);
+ err = inflate(&(zself->zst), Z_SYNC_FLUSH);
Py_END_ALLOW_THREADS
- if (err == Z_NEED_DICT && self->zdict != NULL) {
+ if (err == Z_NEED_DICT && zself->zdict != NULL) {
Py_buffer zdict_buf;
- if (PyObject_GetBuffer(self->zdict, &zdict_buf, PyBUF_SIMPLE) == -1) {
+ if (PyObject_GetBuffer(zself->zdict, &zdict_buf, PyBUF_SIMPLE) == -1) {
Py_DECREF(RetVal);
RetVal = NULL;
goto error;
}
- err = inflateSetDictionary(&(self->zst), zdict_buf.buf, zdict_buf.len);
+ err = inflateSetDictionary(&(zself->zst), zdict_buf.buf, zdict_buf.len);
PyBuffer_Release(&zdict_buf);
if (err != Z_OK) {
- zlib_error(self->zst, err, "while decompressing data");
+ zlib_error(zself->zst, err, "while decompressing data");
Py_DECREF(RetVal);
RetVal = NULL;
goto error;
}
/* Repeat the call to inflate. */
Py_BEGIN_ALLOW_THREADS
- err = inflate(&(self->zst), Z_SYNC_FLUSH);
+ err = inflate(&(zself->zst), Z_SYNC_FLUSH);
Py_END_ALLOW_THREADS
}
/* While Z_OK and the output buffer is full, there might be more output.
So extend the output buffer and try again.
*/
- while (err == Z_OK && self->zst.avail_out == 0) {
+ while (err == Z_OK && zself->zst.avail_out == 0) {
/* If max_length set, don't continue decompressing if we've already
reached the limit.
*/
@@ -698,20 +770,19 @@ PyZlib_objdecompress(compobject *self, PyObject *args)
length = max_length;
if (_PyBytes_Resize(&RetVal, length) < 0) {
- Py_DECREF(RetVal);
- RetVal = NULL;
+ Py_CLEAR(RetVal);
goto error;
}
- self->zst.next_out =
+ zself->zst.next_out =
(unsigned char *)PyBytes_AS_STRING(RetVal) + old_length;
- self->zst.avail_out = length - old_length;
+ zself->zst.avail_out = length - old_length;
Py_BEGIN_ALLOW_THREADS
- err = inflate(&(self->zst), Z_SYNC_FLUSH);
+ err = inflate(&(zself->zst), Z_SYNC_FLUSH);
Py_END_ALLOW_THREADS
}
- if (save_unconsumed_input(self, err) < 0) {
+ if (save_unconsumed_input(zself, err) < 0) {
Py_DECREF(RetVal);
RetVal = NULL;
goto error;
@@ -720,27 +791,24 @@ PyZlib_objdecompress(compobject *self, PyObject *args)
if (err == Z_STREAM_END) {
/* This is the logical place to call inflateEnd, but the old behaviour
of only calling it on flush() is preserved. */
- self->eof = 1;
+ zself->eof = 1;
} else if (err != Z_OK && err != Z_BUF_ERROR) {
/* We will only get Z_BUF_ERROR if the output buffer was full
but there wasn't more output when we tried again, so it is
not an error condition.
*/
- zlib_error(self->zst, err, "while decompressing data");
+ zlib_error(zself->zst, err, "while decompressing data");
Py_DECREF(RetVal);
RetVal = NULL;
goto error;
}
- if (_PyBytes_Resize(&RetVal, self->zst.total_out - start_total_out) < 0) {
- Py_DECREF(RetVal);
- RetVal = NULL;
+ if (_PyBytes_Resize(&RetVal, zself->zst.total_out - start_total_out) < 0) {
+ Py_CLEAR(RetVal);
}
error:
- LEAVE_ZLIB(self);
- error_outer:
- PyBuffer_Release(&pinput);
+ LEAVE_ZLIB(zself);
return RetVal;
}
@@ -787,8 +855,7 @@ PyZlib_flush(compobject *self, PyObject *args)
so extend the output buffer and try again */
while (err == Z_OK && self->zst.avail_out == 0) {
if (_PyBytes_Resize(&RetVal, length << 1) < 0) {
- Py_DECREF(RetVal);
- RetVal = NULL;
+ Py_CLEAR(RetVal);
goto error;
}
self->zst.next_out =
@@ -827,8 +894,7 @@ PyZlib_flush(compobject *self, PyObject *args)
}
if (_PyBytes_Resize(&RetVal, self->zst.total_out - start_total_out) < 0) {
- Py_DECREF(RetVal);
- RetVal = NULL;
+ Py_CLEAR(RetVal);
}
error:
@@ -838,12 +904,27 @@ PyZlib_flush(compobject *self, PyObject *args)
}
#ifdef HAVE_ZLIB_COPY
-PyDoc_STRVAR(comp_copy__doc__,
-"copy() -- Return a copy of the compression object.");
+
+/*[clinic]
+
+zlib.copy
+
+Return a copy of the compression object.
+[clinic]*/
+
+PyDoc_STRVAR(zlib_copy__doc__,
+"Return a copy of the compression object.\n"
+"\n"
+"zlib.copy()");
+
+#define ZLIB_COPY_METHODDEF \
+ {"copy", (PyCFunction)zlib_copy, METH_NOARGS, zlib_copy__doc__},
static PyObject *
-PyZlib_copy(compobject *self)
+zlib_copy(PyObject *self)
+/*[clinic checksum: 7b648de2c1f933ba2b9fa17331ff1a44d9a4a740]*/
{
+ compobject *zself = (compobject *)self;
compobject *retval = NULL;
int err;
@@ -853,8 +934,8 @@ PyZlib_copy(compobject *self)
/* Copy the zstream state
* We use ENTER_ZLIB / LEAVE_ZLIB to make this thread-safe
*/
- ENTER_ZLIB(self);
- err = deflateCopy(&retval->zst, &self->zst);
+ ENTER_ZLIB(zself);
+ err = deflateCopy(&retval->zst, &zself->zst);
switch(err) {
case(Z_OK):
break;
@@ -866,28 +947,28 @@ PyZlib_copy(compobject *self)
"Can't allocate memory for compression object");
goto error;
default:
- zlib_error(self->zst, err, "while copying compression object");
+ zlib_error(zself->zst, err, "while copying compression object");
goto error;
}
- Py_INCREF(self->unused_data);
- Py_INCREF(self->unconsumed_tail);
- Py_XINCREF(self->zdict);
+ Py_INCREF(zself->unused_data);
+ Py_INCREF(zself->unconsumed_tail);
+ Py_XINCREF(zself->zdict);
Py_XDECREF(retval->unused_data);
Py_XDECREF(retval->unconsumed_tail);
Py_XDECREF(retval->zdict);
- retval->unused_data = self->unused_data;
- retval->unconsumed_tail = self->unconsumed_tail;
- retval->zdict = self->zdict;
- retval->eof = self->eof;
+ retval->unused_data = zself->unused_data;
+ retval->unconsumed_tail = zself->unconsumed_tail;
+ retval->zdict = zself->zdict;
+ retval->eof = zself->eof;
/* Mark it as being initialized */
retval->is_initialised = 1;
- LEAVE_ZLIB(self);
+ LEAVE_ZLIB(zself);
return (PyObject *)retval;
error:
- LEAVE_ZLIB(self);
+ LEAVE_ZLIB(zself);
Py_XDECREF(retval);
return NULL;
}
@@ -988,8 +1069,7 @@ PyZlib_unflush(compobject *self, PyObject *args)
so extend the output buffer and try again */
while ((err == Z_OK || err == Z_BUF_ERROR) && self->zst.avail_out == 0) {
if (_PyBytes_Resize(&retval, length << 1) < 0) {
- Py_DECREF(retval);
- retval = NULL;
+ Py_CLEAR(retval);
goto error;
}
self->zst.next_out = (Byte *)PyBytes_AS_STRING(retval) + length;
@@ -1021,8 +1101,7 @@ PyZlib_unflush(compobject *self, PyObject *args)
}
if (_PyBytes_Resize(&retval, self->zst.total_out - start_total_out) < 0) {
- Py_DECREF(retval);
- retval = NULL;
+ Py_CLEAR(retval);
}
error:
@@ -1039,16 +1118,14 @@ static PyMethodDef comp_methods[] =
{"flush", (binaryfunc)PyZlib_flush, METH_VARARGS,
comp_flush__doc__},
#ifdef HAVE_ZLIB_COPY
- {"copy", (PyCFunction)PyZlib_copy, METH_NOARGS,
- comp_copy__doc__},
+ ZLIB_COPY_METHODDEF
#endif
{NULL, NULL}
};
static PyMethodDef Decomp_methods[] =
{
- {"decompress", (binaryfunc)PyZlib_objdecompress, METH_VARARGS,
- decomp_decompress__doc__},
+ ZLIB_DECOMPRESS_METHODDEF
{"flush", (binaryfunc)PyZlib_unflush, METH_VARARGS,
decomp_flush__doc__},
#ifdef HAVE_ZLIB_COPY
@@ -1094,10 +1171,10 @@ PyZlib_adler32(PyObject *self, PyObject *args)
buf += (size_t) UINT_MAX;
len -= (size_t) UINT_MAX;
}
- adler32val = adler32(adler32val, buf, len);
+ adler32val = adler32(adler32val, buf, (unsigned int)len);
Py_END_ALLOW_THREADS
} else {
- adler32val = adler32(adler32val, pbuf.buf, pbuf.len);
+ adler32val = adler32(adler32val, pbuf.buf, (unsigned int)pbuf.len);
}
PyBuffer_Release(&pbuf);
return PyLong_FromUnsignedLong(adler32val & 0xffffffffU);
@@ -1132,10 +1209,10 @@ PyZlib_crc32(PyObject *self, PyObject *args)
buf += (size_t) UINT_MAX;
len -= (size_t) UINT_MAX;
}
- signed_val = crc32(crc32val, buf, len);
+ signed_val = crc32(crc32val, buf, (unsigned int)len);
Py_END_ALLOW_THREADS
} else {
- signed_val = crc32(crc32val, pbuf.buf, pbuf.len);
+ signed_val = crc32(crc32val, pbuf.buf, (unsigned int)pbuf.len);
}
PyBuffer_Release(&pbuf);
return PyLong_FromUnsignedLong(signed_val & 0xffffffffU);
@@ -1266,20 +1343,20 @@ PyInit_zlib(void)
Py_INCREF(ZlibError);
PyModule_AddObject(m, "error", ZlibError);
}
- PyModule_AddIntConstant(m, "MAX_WBITS", MAX_WBITS);
- PyModule_AddIntConstant(m, "DEFLATED", DEFLATED);
- PyModule_AddIntConstant(m, "DEF_MEM_LEVEL", DEF_MEM_LEVEL);
- PyModule_AddIntConstant(m, "Z_BEST_SPEED", Z_BEST_SPEED);
- PyModule_AddIntConstant(m, "Z_BEST_COMPRESSION", Z_BEST_COMPRESSION);
- PyModule_AddIntConstant(m, "Z_DEFAULT_COMPRESSION", Z_DEFAULT_COMPRESSION);
- PyModule_AddIntConstant(m, "Z_FILTERED", Z_FILTERED);
- PyModule_AddIntConstant(m, "Z_HUFFMAN_ONLY", Z_HUFFMAN_ONLY);
- PyModule_AddIntConstant(m, "Z_DEFAULT_STRATEGY", Z_DEFAULT_STRATEGY);
-
- PyModule_AddIntConstant(m, "Z_FINISH", Z_FINISH);
- PyModule_AddIntConstant(m, "Z_NO_FLUSH", Z_NO_FLUSH);
- PyModule_AddIntConstant(m, "Z_SYNC_FLUSH", Z_SYNC_FLUSH);
- PyModule_AddIntConstant(m, "Z_FULL_FLUSH", Z_FULL_FLUSH);
+ PyModule_AddIntMacro(m, MAX_WBITS);
+ PyModule_AddIntMacro(m, DEFLATED);
+ PyModule_AddIntMacro(m, DEF_MEM_LEVEL);
+ PyModule_AddIntMacro(m, Z_BEST_SPEED);
+ PyModule_AddIntMacro(m, Z_BEST_COMPRESSION);
+ PyModule_AddIntMacro(m, Z_DEFAULT_COMPRESSION);
+ PyModule_AddIntMacro(m, Z_FILTERED);
+ PyModule_AddIntMacro(m, Z_HUFFMAN_ONLY);
+ PyModule_AddIntMacro(m, Z_DEFAULT_STRATEGY);
+
+ PyModule_AddIntMacro(m, Z_FINISH);
+ PyModule_AddIntMacro(m, Z_NO_FLUSH);
+ PyModule_AddIntMacro(m, Z_SYNC_FLUSH);
+ PyModule_AddIntMacro(m, Z_FULL_FLUSH);
ver = PyUnicode_FromString(ZLIB_VERSION);
if (ver != NULL)