diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2014-02-09 13:46:20 +0200 |
---|---|---|
committer | Serhiy Storchaka <storchaka@gmail.com> | 2014-02-09 13:46:20 +0200 |
commit | 2d67fc060d1a3c7fdab950440fdbd3b6d98e4b4d (patch) | |
tree | db1b115222a9ecc36e381de6b49d51e8fed52570 /Modules/zlibmodule.c | |
parent | c2d47e10f770f449ed811e1de8a6fd8a6cb408c9 (diff) | |
parent | 2883d78b1932e3d3d15495380bfe2cdf0d1a7061 (diff) | |
download | cpython-2d67fc060d1a3c7fdab950440fdbd3b6d98e4b4d.tar.gz |
Issue #20437: Fixed 22 potential bugs when deleting objects references.
Diffstat (limited to 'Modules/zlibmodule.c')
-rw-r--r-- | Modules/zlibmodule.c | 710 |
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) |