summaryrefslogtreecommitdiff
path: root/Modules/zlibmodule.c
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2014-02-09 13:46:20 +0200
committerSerhiy Storchaka <storchaka@gmail.com>2014-02-09 13:46:20 +0200
commit2d67fc060d1a3c7fdab950440fdbd3b6d98e4b4d (patch)
treedb1b115222a9ecc36e381de6b49d51e8fed52570 /Modules/zlibmodule.c
parentc2d47e10f770f449ed811e1de8a6fd8a6cb408c9 (diff)
parent2883d78b1932e3d3d15495380bfe2cdf0d1a7061 (diff)
downloadcpython-2d67fc060d1a3c7fdab950440fdbd3b6d98e4b4d.tar.gz
Issue #20437: Fixed 22 potential bugs when deleting objects references.
Diffstat (limited to 'Modules/zlibmodule.c')
-rw-r--r--Modules/zlibmodule.c710
1 files changed, 406 insertions, 304 deletions
diff --git a/Modules/zlibmodule.c b/Modules/zlibmodule.c
index 1d1072dcea..52744b967e 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) \
@@ -27,10 +28,9 @@
#else
# define DEF_MEM_LEVEL MAX_MEM_LEVEL
#endif
-#define DEF_WBITS MAX_WBITS
-/* The output buffer will be increased in chunks of DEFAULTALLOC bytes. */
-#define DEFAULTALLOC (16*1024)
+/* Initial buffer size. */
+#define DEF_BUF_SIZE (16*1024)
static PyTypeObject Comptype;
static PyTypeObject Decomptype;
@@ -80,35 +80,13 @@ zlib_error(z_stream zst, int err, char *msg)
PyErr_Format(ZlibError, "Error %d %s: %.200s", err, msg, zmsg);
}
-PyDoc_STRVAR(compressobj__doc__,
-"compressobj(level=-1, method=DEFLATED, wbits=15, memlevel=8,\n"
-" strategy=Z_DEFAULT_STRATEGY[, zdict])\n"
-" -- Return a compressor object.\n"
-"\n"
-"level is the compression level (an integer in the range 0-9; default is 6).\n"
-"Higher compression levels are slower, but produce smaller results.\n"
-"\n"
-"method is the compression algorithm. If given, this must be DEFLATED.\n"
-"\n"
-"wbits is the base two logarithm of the window size (range: 8..15).\n"
-"\n"
-"memlevel controls the amount of memory used for internal compression state.\n"
-"Valid values range from 1 to 9. Higher values result in higher memory usage,\n"
-"faster compression, and smaller output.\n"
-"\n"
-"strategy is used to tune the compression algorithm. Possible values are\n"
-"Z_DEFAULT_STRATEGY, Z_FILTERED, and Z_HUFFMAN_ONLY.\n"
-"\n"
-"zdict is the predefined compression dictionary - a sequence of bytes\n"
-"containing subsequences that are likely to occur in the input data.");
-
-PyDoc_STRVAR(decompressobj__doc__,
-"decompressobj([wbits[, zdict]]) -- Return a decompressor object.\n"
-"\n"
-"Optional arg wbits is the window buffer size.\n"
-"\n"
-"Optional arg zdict is the predefined compression dictionary. This must be\n"
-"the same dictionary as used by the compressor that produced the input data.");
+/*[clinic input]
+output preset file
+module zlib
+class zlib.Compress "compobject *" "&Comptype"
+class zlib.Decompress "compobject *" "&Decomptype"
+[clinic start generated code]*/
+/*[clinic end generated code: output=da39a3ee5e6b4b0d input=bfd4c340573ba91d]*/
static compobject *
newcompobject(PyTypeObject *type)
@@ -132,40 +110,63 @@ 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;
}
-PyDoc_STRVAR(compress__doc__,
-"compress(string[, level]) -- Returned compressed string.\n"
-"\n"
-"Optional arg level is the compression level, in 0-9.");
+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);
+}
+
+/*[clinic input]
+zlib.compress
+
+ bytes: Py_buffer
+ Binary data to be compressed.
+ level: int(c_default="Z_DEFAULT_COMPRESSION") = Z_DEFAULT_COMPRESSION
+ Compression level, in 0-9.
+ /
+
+Returns a bytes object containing compressed data.
+[clinic start generated code]*/
static PyObject *
-PyZlib_compress(PyObject *self, PyObject *args)
+zlib_compress_impl(PyModuleDef *module, Py_buffer *bytes, int level)
+/*[clinic end generated code: output=5d7dd4588788efd3 input=be3abe9934bda4b3]*/
{
PyObject *ReturnVal = NULL;
- Py_buffer pinput;
Byte *input, *output = NULL;
unsigned int length;
- int level=Z_DEFAULT_COMPRESSION, err;
+ int err;
z_stream zst;
- /* require Python string object, optional 'level' arg */
- if (!PyArg_ParseTuple(args, "y*|i:compress", &pinput, &level))
- return NULL;
-
- if (pinput.len > UINT_MAX) {
+ if ((size_t)bytes->len > UINT_MAX) {
PyErr_SetString(PyExc_OverflowError,
"Size does not fit in an unsigned int");
goto error;
}
- input = pinput.buf;
- length = pinput.len;
+ input = bytes->buf;
+ length = (unsigned int)bytes->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 +176,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;
@@ -217,56 +219,100 @@ PyZlib_compress(PyObject *self, PyObject *args)
zlib_error(zst, err, "while finishing compression");
error:
- PyBuffer_Release(&pinput);
- free(output);
+ PyMem_Free(output);
return ReturnVal;
}
-PyDoc_STRVAR(decompress__doc__,
-"decompress(string[, wbits[, bufsize]]) -- Return decompressed string.\n"
-"\n"
-"Optional arg wbits is the window buffer size. Optional arg bufsize is\n"
-"the initial output buffer size.");
+/*[python input]
+
+class uint_converter(CConverter):
+ type = 'unsigned int'
+ converter = 'uint_converter'
+ c_ignored_default = "0"
+
+[python start generated code]*/
+/*[python end generated code: output=da39a3ee5e6b4b0d input=22263855f7a3ebfd]*/
+
+static int
+uint_converter(PyObject *obj, void *ptr)
+{
+ long val;
+ unsigned long uval;
+
+ val = PyLong_AsLong(obj);
+ if (val == -1 && PyErr_Occurred()) {
+ uval = PyLong_AsUnsignedLong(obj);
+ if (uval == (unsigned long)-1 && PyErr_Occurred())
+ return 0;
+ }
+ else {
+ if (val < 0) {
+ PyErr_SetString(PyExc_ValueError,
+ "value must be positive");
+ return 0;
+ }
+ uval = (unsigned long)val;
+ }
+
+ if (uval > UINT_MAX) {
+ PyErr_SetString(PyExc_OverflowError,
+ "Python int too large for C unsigned int");
+ return 0;
+ }
+
+ *(unsigned int *)ptr = Py_SAFE_DOWNCAST(uval, unsigned long, unsigned int);
+ return 1;
+}
+
+/*[clinic input]
+zlib.decompress
+
+ data: Py_buffer
+ Compressed data.
+ wbits: int(c_default="MAX_WBITS") = MAX_WBITS
+ The window buffer size.
+ bufsize: uint(c_default="DEF_BUF_SIZE") = DEF_BUF_SIZE
+ The initial output buffer size.
+ /
+
+Returns a bytes object containing the uncompressed data.
+[clinic start generated code]*/
static PyObject *
-PyZlib_decompress(PyObject *self, PyObject *args)
+zlib_decompress_impl(PyModuleDef *module, Py_buffer *data, int wbits, unsigned int bufsize)
+/*[clinic end generated code: output=9e5464e72df9cb5f input=0f4b9abb7103f50e]*/
{
PyObject *result_str = NULL;
- Py_buffer pinput;
Byte *input;
unsigned int length;
int err;
- int wsize=DEF_WBITS;
- Py_ssize_t r_strlen=DEFAULTALLOC;
+ unsigned int new_bufsize;
z_stream zst;
- if (!PyArg_ParseTuple(args, "y*|in:decompress",
- &pinput, &wsize, &r_strlen))
- return NULL;
-
- if (pinput.len > UINT_MAX) {
+ if ((size_t)data->len > UINT_MAX) {
PyErr_SetString(PyExc_OverflowError,
"Size does not fit in an unsigned int");
goto error;
}
- input = pinput.buf;
- length = pinput.len;
+ input = data->buf;
+ length = (unsigned int)data->len;
- if (r_strlen <= 0)
- r_strlen = 1;
+ if (bufsize == 0)
+ bufsize = 1;
zst.avail_in = length;
- zst.avail_out = r_strlen;
+ zst.avail_out = bufsize;
- if (!(result_str = PyBytes_FromStringAndSize(NULL, r_strlen)))
+ if (!(result_str = PyBytes_FromStringAndSize(NULL, bufsize)))
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);
+ err = inflateInit2(&zst, wbits);
switch(err) {
case(Z_OK):
@@ -303,14 +349,18 @@ PyZlib_decompress(PyObject *self, PyObject *args)
/* fall through */
case(Z_OK):
/* need more memory */
- if (_PyBytes_Resize(&result_str, r_strlen << 1) < 0) {
+ if (bufsize <= (UINT_MAX >> 1))
+ new_bufsize = bufsize << 1;
+ else
+ new_bufsize = UINT_MAX;
+ if (_PyBytes_Resize(&result_str, new_bufsize) < 0) {
inflateEnd(&zst);
goto error;
}
zst.next_out =
- (unsigned char *)PyBytes_AS_STRING(result_str) + r_strlen;
- zst.avail_out = r_strlen;
- r_strlen = r_strlen << 1;
+ (unsigned char *)PyBytes_AS_STRING(result_str) + bufsize;
+ zst.avail_out = bufsize;
+ bufsize = new_bufsize;
break;
default:
inflateEnd(&zst);
@@ -328,46 +378,67 @@ PyZlib_decompress(PyObject *self, PyObject *args)
if (_PyBytes_Resize(&result_str, zst.total_out) < 0)
goto error;
- PyBuffer_Release(&pinput);
return result_str;
error:
- PyBuffer_Release(&pinput);
Py_XDECREF(result_str);
return NULL;
}
+/*[clinic input]
+zlib.compressobj
+
+ level: int(c_default="Z_DEFAULT_COMPRESSION") = Z_DEFAULT_COMPRESSION
+ The compression level (an integer in the range 0-9; default is 6).
+ Higher compression levels are slower, but produce smaller results.
+ method: int(c_default="DEFLATED") = DEFLATED
+ The compression algorithm. If given, this must be DEFLATED.
+ wbits: int(c_default="MAX_WBITS") = MAX_WBITS
+ The base two logarithm of the window size (range: 8..15).
+ memLevel: int(c_default="DEF_MEM_LEVEL") = DEF_MEM_LEVEL
+ Controls the amount of memory used for internal compression state.
+ Valid values range from 1 to 9. Higher values result in higher memory
+ usage, faster compression, and smaller output.
+ strategy: int(c_default="Z_DEFAULT_STRATEGY") = Z_DEFAULT_STRATEGY
+ Used to tune the compression algorithm. Possible values are
+ Z_DEFAULT_STRATEGY, Z_FILTERED, and Z_HUFFMAN_ONLY.
+ zdict: Py_buffer = None
+ The predefined compression dictionary - a sequence of bytes
+ containing subsequences that are likely to occur in the input data.
+
+Return a compressor object.
+[clinic start generated code]*/
+
static PyObject *
-PyZlib_compressobj(PyObject *selfptr, PyObject *args, PyObject *kwargs)
+zlib_compressobj_impl(PyModuleDef *module, int level, int method, int wbits, int memLevel, int strategy, Py_buffer *zdict)
+/*[clinic end generated code: output=89e5a6c1449caa9e input=b034847f8821f6af]*/
{
- compobject *self;
- int level=Z_DEFAULT_COMPRESSION, method=DEFLATED;
- int wbits=MAX_WBITS, memLevel=DEF_MEM_LEVEL, strategy=0, err;
- Py_buffer zdict;
- static char *kwlist[] = {"level", "method", "wbits",
- "memLevel", "strategy", "zdict", NULL};
-
- zdict.buf = NULL; /* Sentinel, so we can tell whether zdict was supplied. */
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iiiiiy*:compressobj",
- kwlist, &level, &method, &wbits,
- &memLevel, &strategy, &zdict))
- return NULL;
+ compobject *self = NULL;
+ int err;
+
+ if (zdict->buf != NULL && (size_t)zdict->len > UINT_MAX) {
+ PyErr_SetString(PyExc_OverflowError,
+ "zdict length does not fit in an unsigned int");
+ goto error;
+ }
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);
switch(err) {
case (Z_OK):
self->is_initialised = 1;
- if (zdict.buf == NULL) {
+ if (zdict->buf == NULL) {
goto success;
} else {
- err = deflateSetDictionary(&self->zst, zdict.buf, zdict.len);
+ err = deflateSetDictionary(&self->zst,
+ zdict->buf, (unsigned int)zdict->len);
switch (err) {
case (Z_OK):
goto success;
@@ -394,22 +465,28 @@ PyZlib_compressobj(PyObject *selfptr, PyObject *args, PyObject *kwargs)
error:
Py_CLEAR(self);
success:
- if (zdict.buf != NULL)
- PyBuffer_Release(&zdict);
return (PyObject*)self;
}
+/*[clinic input]
+zlib.decompressobj
+
+ wbits: int(c_default="MAX_WBITS") = MAX_WBITS
+ The window buffer size.
+ zdict: object(c_default="NULL") = b''
+ The predefined compression dictionary. This must be the same
+ dictionary as used by the compressor that produced the input data.
+
+Return a decompressor object.
+[clinic start generated code]*/
+
static PyObject *
-PyZlib_decompressobj(PyObject *selfptr, PyObject *args, PyObject *kwargs)
+zlib_decompressobj_impl(PyModuleDef *module, int wbits, PyObject *zdict)
+/*[clinic end generated code: output=8ccd583fbd631798 input=67f05145a6920127]*/
{
- static char *kwlist[] = {"wbits", "zdict", NULL};
- int wbits=DEF_WBITS, err;
+ int err;
compobject *self;
- PyObject *zdict=NULL;
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:decompressobj",
- kwlist, &wbits, &zdict))
- return NULL;
if (zdict != NULL && !PyObject_CheckBuffer(zdict)) {
PyErr_SetString(PyExc_TypeError,
"zdict argument must support the buffer protocol");
@@ -419,8 +496,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) {
@@ -476,37 +554,41 @@ Decomp_dealloc(compobject *self)
Dealloc(self);
}
-PyDoc_STRVAR(comp_compress__doc__,
-"compress(data) -- Return a string containing data compressed.\n"
-"\n"
-"After calling this function, some of the input data may still\n"
-"be stored in internal buffers for later processing.\n"
-"Call the flush() method to clear these buffers.");
+/*[clinic input]
+zlib.Compress.compress
+
+ data: Py_buffer
+ Binary data to be compressed.
+ /
+Returns a bytes object containing compressed 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 start generated code]*/
static PyObject *
-PyZlib_objcompress(compobject *self, PyObject *args)
+zlib_Compress_compress_impl(compobject *self, Py_buffer *data)
+/*[clinic end generated code: output=5d5cd791cbc6a7f4 input=0d95908d6e64fab8]*/
{
int err;
unsigned int inplen;
- Py_ssize_t length = DEFAULTALLOC;
- PyObject *RetVal = NULL;
- Py_buffer pinput;
+ unsigned int length = DEF_BUF_SIZE, new_length;
+ PyObject *RetVal;
Byte *input;
unsigned long start_total_out;
- if (!PyArg_ParseTuple(args, "y*:compress", &pinput))
- return NULL;
- if (pinput.len > UINT_MAX) {
+ if ((size_t)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 = (unsigned int)data->len;
if (!(RetVal = PyBytes_FromStringAndSize(NULL, length)))
- goto error_outer;
+ return NULL;
ENTER_ZLIB(self);
@@ -523,15 +605,18 @@ PyZlib_objcompress(compobject *self, PyObject *args)
/* 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) {
- if (_PyBytes_Resize(&RetVal, length << 1) < 0) {
- Py_DECREF(RetVal);
- RetVal = NULL;
- goto error;
+ if (length <= (UINT_MAX >> 1))
+ new_length = length << 1;
+ else
+ new_length = UINT_MAX;
+ if (_PyBytes_Resize(&RetVal, new_length) < 0) {
+ Py_CLEAR(RetVal);
+ goto done;
}
self->zst.next_out =
(unsigned char *)PyBytes_AS_STRING(RetVal) + length;
self->zst.avail_out = length;
- length = length << 1;
+ length = new_length;
Py_BEGIN_ALLOW_THREADS
err = deflate(&(self->zst), Z_NO_FLUSH);
@@ -544,19 +629,15 @@ PyZlib_objcompress(compobject *self, PyObject *args)
if (err != Z_OK && err != Z_BUF_ERROR) {
zlib_error(self->zst, err, "while compressing data");
- Py_DECREF(RetVal);
- RetVal = NULL;
- goto error;
+ Py_CLEAR(RetVal);
+ goto done;
}
if (_PyBytes_Resize(&RetVal, self->zst.total_out - start_total_out) < 0) {
- Py_DECREF(RetVal);
- RetVal = NULL;
+ Py_CLEAR(RetVal);
}
- error:
+ done:
LEAVE_ZLIB(self);
- error_outer:
- PyBuffer_Release(&pinput);
return RetVal;
}
@@ -572,7 +653,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 ((size_t)self->zst.avail_in > (size_t)UINT_MAX - (size_t)old_size) {
PyErr_NoMemory();
return -1;
}
@@ -603,55 +684,50 @@ 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"
-"\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.");
+/*[clinic input]
+zlib.Decompress.decompress
+
+ data: Py_buffer
+ The binary data to decompress.
+ max_length: uint = 0
+ The maximum allowable length of the decompressed data.
+ Unconsumed input data will be stored in
+ the unconsumed_tail attribute.
+ /
+
+Return a bytes object 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 start generated code]*/
static PyObject *
-PyZlib_objdecompress(compobject *self, PyObject *args)
+zlib_Decompress_decompress_impl(compobject *self, Py_buffer *data, unsigned int max_length)
+/*[clinic end generated code: output=755cccc9087bfe55 input=02cfc047377cec86]*/
{
- int err, max_length = 0;
- unsigned int inplen;
- Py_ssize_t old_length, length = DEFAULTALLOC;
+ int err;
+ unsigned int old_length, length = DEF_BUF_SIZE;
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 ((size_t)data->len > UINT_MAX) {
PyErr_SetString(PyExc_OverflowError,
"Size does not fit in an unsigned int");
- goto error_outer;
- }
- input = pinput.buf;
- inplen = pinput.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);
start_total_out = self->zst.total_out;
- self->zst.avail_in = inplen;
- self->zst.next_in = input;
+ self->zst.avail_in = (unsigned int)data->len;
+ self->zst.next_in = data->buf;
self->zst.avail_out = length;
self->zst.next_out = (unsigned char *)PyBytes_AS_STRING(RetVal);
@@ -666,12 +742,21 @@ PyZlib_objdecompress(compobject *self, PyObject *args)
RetVal = NULL;
goto error;
}
- err = inflateSetDictionary(&(self->zst), zdict_buf.buf, zdict_buf.len);
+
+ if ((size_t)zdict_buf.len > UINT_MAX) {
+ PyErr_SetString(PyExc_OverflowError,
+ "zdict length does not fit in an unsigned int");
+ PyBuffer_Release(&zdict_buf);
+ Py_CLEAR(RetVal);
+ goto error;
+ }
+
+ err = inflateSetDictionary(&(self->zst),
+ zdict_buf.buf, (unsigned int)zdict_buf.len);
PyBuffer_Release(&zdict_buf);
if (err != Z_OK) {
zlib_error(self->zst, err, "while decompressing data");
- Py_DECREF(RetVal);
- RetVal = NULL;
+ Py_CLEAR(RetVal);
goto error;
}
/* Repeat the call to inflate. */
@@ -697,8 +782,7 @@ 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 =
@@ -732,39 +816,39 @@ PyZlib_objdecompress(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:
LEAVE_ZLIB(self);
- error_outer:
- PyBuffer_Release(&pinput);
return RetVal;
}
-PyDoc_STRVAR(comp_flush__doc__,
-"flush( [mode] ) -- Return a string containing any remaining compressed data.\n"
-"\n"
-"mode can be one of the constants Z_SYNC_FLUSH, Z_FULL_FLUSH, Z_FINISH; the\n"
-"default value used when mode is not specified is Z_FINISH.\n"
-"If mode == Z_FINISH, the compressor object can no longer be used after\n"
-"calling the flush() method. Otherwise, more data can still be compressed.");
+/*[clinic input]
+zlib.Compress.flush
+
+ mode: int(c_default="Z_FINISH") = zlib.Z_FINISH
+ One of the constants Z_SYNC_FLUSH, Z_FULL_FLUSH, Z_FINISH.
+ If mode == Z_FINISH, the compressor object can no longer be
+ used after calling the flush() method. Otherwise, more data
+ can still be compressed.
+ /
+
+Return a bytes object containing any remaining compressed data.
+[clinic start generated code]*/
static PyObject *
-PyZlib_flush(compobject *self, PyObject *args)
+zlib_Compress_flush_impl(compobject *self, int mode)
+/*[clinic end generated code: output=a203f4cefc9de727 input=73ed066794bd15bc]*/
{
- int err, length = DEFAULTALLOC;
+ int err;
+ unsigned int length = DEF_BUF_SIZE, new_length;
PyObject *RetVal;
- int flushmode = Z_FINISH;
unsigned long start_total_out;
- if (!PyArg_ParseTuple(args, "|i:flush", &flushmode))
- return NULL;
-
/* Flushing with Z_NO_FLUSH is a no-op, so there's no point in
doing any work at all; just return an empty string. */
- if (flushmode == Z_NO_FLUSH) {
+ if (mode == Z_NO_FLUSH) {
return PyBytes_FromStringAndSize(NULL, 0);
}
@@ -779,31 +863,34 @@ PyZlib_flush(compobject *self, PyObject *args)
self->zst.next_out = (unsigned char *)PyBytes_AS_STRING(RetVal);
Py_BEGIN_ALLOW_THREADS
- err = deflate(&(self->zst), flushmode);
+ err = deflate(&(self->zst), mode);
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) {
- if (_PyBytes_Resize(&RetVal, length << 1) < 0) {
- Py_DECREF(RetVal);
- RetVal = NULL;
+ if (length <= (UINT_MAX >> 1))
+ new_length = length << 1;
+ else
+ new_length = UINT_MAX;
+ if (_PyBytes_Resize(&RetVal, new_length) < 0) {
+ Py_CLEAR(RetVal);
goto error;
}
self->zst.next_out =
(unsigned char *)PyBytes_AS_STRING(RetVal) + length;
self->zst.avail_out = length;
- length = length << 1;
+ length = new_length;
Py_BEGIN_ALLOW_THREADS
- err = deflate(&(self->zst), flushmode);
+ err = deflate(&(self->zst), mode);
Py_END_ALLOW_THREADS
}
- /* If flushmode is Z_FINISH, we also have to call deflateEnd() to free
+ /* If mode is Z_FINISH, we also have to call deflateEnd() to free
various data structures. Note we should only get Z_STREAM_END when
- flushmode is Z_FINISH, but checking both for safety*/
- if (err == Z_STREAM_END && flushmode == Z_FINISH) {
+ mode is Z_FINISH, but checking both for safety*/
+ if (err == Z_STREAM_END && mode == Z_FINISH) {
err = deflateEnd(&(self->zst));
if (err != Z_OK) {
zlib_error(self->zst, err, "while finishing compression");
@@ -826,8 +913,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:
@@ -837,11 +923,16 @@ PyZlib_flush(compobject *self, PyObject *args)
}
#ifdef HAVE_ZLIB_COPY
-PyDoc_STRVAR(comp_copy__doc__,
-"copy() -- Return a copy of the compression object.");
+
+/*[clinic input]
+zlib.Compress.copy
+
+Return a copy of the compression object.
+[clinic start generated code]*/
static PyObject *
-PyZlib_copy(compobject *self)
+zlib_Compress_copy_impl(compobject *self)
+/*[clinic end generated code: output=5144aa153c21e805 input=c656351f94b82718]*/
{
compobject *retval = NULL;
int err;
@@ -891,11 +982,15 @@ error:
return NULL;
}
-PyDoc_STRVAR(decomp_copy__doc__,
-"copy() -- Return a copy of the decompression object.");
+/*[clinic input]
+zlib.Decompress.copy
+
+Return a copy of the decompression object.
+[clinic start generated code]*/
static PyObject *
-PyZlib_uncopy(compobject *self)
+zlib_Decompress_copy_impl(compobject *self)
+/*[clinic end generated code: output=02a883a2a510c8cc input=ba6c3e96712a596b]*/
{
compobject *retval = NULL;
int err;
@@ -947,34 +1042,43 @@ error:
}
#endif
-PyDoc_STRVAR(decomp_flush__doc__,
-"flush( [length] ) -- Return a string containing any remaining\n"
-"decompressed data. length, if given, is the initial size of the\n"
-"output buffer.\n"
-"\n"
-"The decompressor object can no longer be used after this call.");
+/*[clinic input]
+zlib.Decompress.flush
+
+ length: uint(c_default="DEF_BUF_SIZE") = zlib.DEF_BUF_SIZE
+ the initial size of the output buffer.
+ /
+
+Return a bytes object containing any remaining decompressed data.
+[clinic start generated code]*/
static PyObject *
-PyZlib_unflush(compobject *self, PyObject *args)
+zlib_Decompress_flush_impl(compobject *self, unsigned int length)
+/*[clinic end generated code: output=db6fb753ab698e22 input=1580956505978993]*/
{
- int err, length = DEFAULTALLOC;
+ int err;
+ unsigned int new_length;
PyObject * retval = NULL;
unsigned long start_total_out;
+ Py_ssize_t size;
- if (!PyArg_ParseTuple(args, "|i:flush", &length))
- return NULL;
- if (length <= 0) {
+ if (length == 0) {
PyErr_SetString(PyExc_ValueError, "length must be greater than zero");
return NULL;
}
+
if (!(retval = PyBytes_FromStringAndSize(NULL, length)))
return NULL;
ENTER_ZLIB(self);
+ size = PyBytes_GET_SIZE(self->unconsumed_tail);
+
start_total_out = self->zst.total_out;
- self->zst.avail_in = PyBytes_GET_SIZE(self->unconsumed_tail);
+ /* save_unconsumed_input() ensures that unconsumed_tail length is lesser
+ or equal than UINT_MAX */
+ self->zst.avail_in = Py_SAFE_DOWNCAST(size, Py_ssize_t, unsigned int);
self->zst.next_in = (Byte *)PyBytes_AS_STRING(self->unconsumed_tail);
self->zst.avail_out = length;
self->zst.next_out = (Byte *)PyBytes_AS_STRING(retval);
@@ -986,14 +1090,17 @@ PyZlib_unflush(compobject *self, PyObject *args)
/* 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 || err == Z_BUF_ERROR) && self->zst.avail_out == 0) {
- if (_PyBytes_Resize(&retval, length << 1) < 0) {
- Py_DECREF(retval);
- retval = NULL;
+ if (length <= (UINT_MAX >> 1))
+ new_length = length << 1;
+ else
+ new_length = UINT_MAX;
+ if (_PyBytes_Resize(&retval, new_length) < 0) {
+ Py_CLEAR(retval);
goto error;
}
self->zst.next_out = (Byte *)PyBytes_AS_STRING(retval) + length;
self->zst.avail_out = length;
- length = length << 1;
+ length = new_length;
Py_BEGIN_ALLOW_THREADS
err = inflate(&(self->zst), Z_FINISH);
@@ -1020,8 +1127,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:
@@ -1031,28 +1137,24 @@ error:
return retval;
}
+#include "clinic/zlibmodule.c.h"
+
static PyMethodDef comp_methods[] =
{
- {"compress", (binaryfunc)PyZlib_objcompress, METH_VARARGS,
- comp_compress__doc__},
- {"flush", (binaryfunc)PyZlib_flush, METH_VARARGS,
- comp_flush__doc__},
+ ZLIB_COMPRESS_COMPRESS_METHODDEF
+ ZLIB_COMPRESS_FLUSH_METHODDEF
#ifdef HAVE_ZLIB_COPY
- {"copy", (PyCFunction)PyZlib_copy, METH_NOARGS,
- comp_copy__doc__},
+ ZLIB_COMPRESS_COPY_METHODDEF
#endif
{NULL, NULL}
};
static PyMethodDef Decomp_methods[] =
{
- {"decompress", (binaryfunc)PyZlib_objdecompress, METH_VARARGS,
- decomp_decompress__doc__},
- {"flush", (binaryfunc)PyZlib_unflush, METH_VARARGS,
- decomp_flush__doc__},
+ ZLIB_DECOMPRESS_DECOMPRESS_METHODDEF
+ ZLIB_DECOMPRESS_FLUSH_METHODDEF
#ifdef HAVE_ZLIB_COPY
- {"copy", (PyCFunction)PyZlib_uncopy, METH_NOARGS,
- decomp_copy__doc__},
+ ZLIB_DECOMPRESS_COPY_METHODDEF
#endif
{NULL, NULL}
};
@@ -1065,96 +1167,95 @@ static PyMemberDef Decomp_members[] = {
{NULL},
};
-PyDoc_STRVAR(adler32__doc__,
-"adler32(string[, start]) -- Compute an Adler-32 checksum of string.\n"
-"\n"
-"An optional starting value can be specified. The returned checksum is\n"
-"an integer.");
+/*[clinic input]
+zlib.adler32
+
+ data: Py_buffer
+ value: unsigned_int(bitwise=True) = 1
+ Starting value of the checksum.
+ /
+
+Compute an Adler-32 checksum of data.
+
+The returned checksum is an integer.
+[clinic start generated code]*/
static PyObject *
-PyZlib_adler32(PyObject *self, PyObject *args)
+zlib_adler32_impl(PyModuleDef *module, Py_buffer *data, unsigned int value)
+/*[clinic end generated code: output=51d6d75ee655c78a input=6ff4557872160e88]*/
{
- unsigned int adler32val = 1; /* adler32(0L, Z_NULL, 0) */
- Py_buffer pbuf;
-
- if (!PyArg_ParseTuple(args, "y*|I:adler32", &pbuf, &adler32val))
- return NULL;
/* Releasing the GIL for very small buffers is inefficient
and may lower performance */
- if (pbuf.len > 1024*5) {
- unsigned char *buf = pbuf.buf;
- Py_ssize_t len = pbuf.len;
+ if (data->len > 1024*5) {
+ unsigned char *buf = data->buf;
+ Py_ssize_t len = data->len;
Py_BEGIN_ALLOW_THREADS
/* Avoid truncation of length for very large buffers. adler32() takes
length as an unsigned int, which may be narrower than Py_ssize_t. */
- while (len > (size_t) UINT_MAX) {
- adler32val = adler32(adler32val, buf, UINT_MAX);
+ while ((size_t)len > UINT_MAX) {
+ value = adler32(value, buf, UINT_MAX);
buf += (size_t) UINT_MAX;
len -= (size_t) UINT_MAX;
}
- adler32val = adler32(adler32val, buf, len);
+ value = adler32(value, buf, (unsigned int)len);
Py_END_ALLOW_THREADS
} else {
- adler32val = adler32(adler32val, pbuf.buf, pbuf.len);
+ value = adler32(value, data->buf, (unsigned int)data->len);
}
- PyBuffer_Release(&pbuf);
- return PyLong_FromUnsignedLong(adler32val & 0xffffffffU);
+ return PyLong_FromUnsignedLong(value & 0xffffffffU);
}
-PyDoc_STRVAR(crc32__doc__,
-"crc32(string[, start]) -- Compute a CRC-32 checksum of string.\n"
-"\n"
-"An optional starting value can be specified. The returned checksum is\n"
-"an integer.");
+/*[clinic input]
+zlib.crc32
+
+ data: Py_buffer
+ value: unsigned_int(bitwise=True) = 0
+ Starting value of the checksum.
+ /
+
+Compute a CRC-32 checksum of data.
+
+The returned checksum is an integer.
+[clinic start generated code]*/
static PyObject *
-PyZlib_crc32(PyObject *self, PyObject *args)
+zlib_crc32_impl(PyModuleDef *module, Py_buffer *data, unsigned int value)
+/*[clinic end generated code: output=c1e986e74fe7b623 input=26c3ed430fa00b4c]*/
{
- unsigned int crc32val = 0; /* crc32(0L, Z_NULL, 0) */
- Py_buffer pbuf;
int signed_val;
- if (!PyArg_ParseTuple(args, "y*|I:crc32", &pbuf, &crc32val))
- return NULL;
/* Releasing the GIL for very small buffers is inefficient
and may lower performance */
- if (pbuf.len > 1024*5) {
- unsigned char *buf = pbuf.buf;
- Py_ssize_t len = pbuf.len;
+ if (data->len > 1024*5) {
+ unsigned char *buf = data->buf;
+ Py_ssize_t len = data->len;
Py_BEGIN_ALLOW_THREADS
/* Avoid truncation of length for very large buffers. crc32() takes
length as an unsigned int, which may be narrower than Py_ssize_t. */
- while (len > (size_t) UINT_MAX) {
- crc32val = crc32(crc32val, buf, UINT_MAX);
+ while ((size_t)len > UINT_MAX) {
+ value = crc32(value, buf, UINT_MAX);
buf += (size_t) UINT_MAX;
len -= (size_t) UINT_MAX;
}
- signed_val = crc32(crc32val, buf, len);
+ signed_val = crc32(value, buf, (unsigned int)len);
Py_END_ALLOW_THREADS
} else {
- signed_val = crc32(crc32val, pbuf.buf, pbuf.len);
+ signed_val = crc32(value, data->buf, (unsigned int)data->len);
}
- PyBuffer_Release(&pbuf);
return PyLong_FromUnsignedLong(signed_val & 0xffffffffU);
}
static PyMethodDef zlib_methods[] =
{
- {"adler32", (PyCFunction)PyZlib_adler32, METH_VARARGS,
- adler32__doc__},
- {"compress", (PyCFunction)PyZlib_compress, METH_VARARGS,
- compress__doc__},
- {"compressobj", (PyCFunction)PyZlib_compressobj, METH_VARARGS|METH_KEYWORDS,
- compressobj__doc__},
- {"crc32", (PyCFunction)PyZlib_crc32, METH_VARARGS,
- crc32__doc__},
- {"decompress", (PyCFunction)PyZlib_decompress, METH_VARARGS,
- decompress__doc__},
- {"decompressobj", (PyCFunction)PyZlib_decompressobj, METH_VARARGS|METH_KEYWORDS,
- decompressobj__doc__},
+ ZLIB_ADLER32_METHODDEF
+ ZLIB_COMPRESS_METHODDEF
+ ZLIB_COMPRESSOBJ_METHODDEF
+ ZLIB_CRC32_METHODDEF
+ ZLIB_DECOMPRESS_METHODDEF
+ ZLIB_DECOMPRESSOBJ_METHODDEF
{NULL, NULL}
};
@@ -1265,20 +1366,21 @@ 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, DEF_BUF_SIZE);
+ 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)