- Thanks to Scott David Daniels, a subtle bug in how the zlib

extension implemented flush() was fixed.  Scott also rewrite the
  zlib test suite using the unittest module.  (SF bug #640230 and
  patch #678531.)

Backport candidate I think.
This commit is contained in:
Guido van Rossum 2003-02-03 20:45:52 +00:00
parent 94c30c0124
commit 7d9ea5013f
5 changed files with 487 additions and 181 deletions

View file

@ -656,27 +656,58 @@ PyDoc_STRVAR(decomp_flush__doc__,
static PyObject *
PyZlib_unflush(compobject *self, PyObject *args)
/*decompressor flush is a no-op because all pending data would have been
flushed by the decompress method. However, this routine previously called
inflateEnd, causing any further decompress or flush calls to raise
exceptions. This behaviour has been preserved.*/
{
int err;
int err, length = DEFAULTALLOC;
PyObject * retval = NULL;
unsigned long start_total_out;
if (!PyArg_ParseTuple(args, ""))
if (!PyArg_ParseTuple(args, "|i:flush", &length))
return NULL;
if (!(retval = PyString_FromStringAndSize(NULL, length)))
return NULL;
ENTER_ZLIB
err = inflateEnd(&(self->zst));
if (err != Z_OK)
zlib_error(self->zst, err, "from inflateEnd()");
else {
self->is_initialised = 0;
retval = PyString_FromStringAndSize(NULL, 0);
start_total_out = self->zst.total_out;
self->zst.avail_out = length;
self->zst.next_out = (Byte *)PyString_AS_STRING(retval);
Py_BEGIN_ALLOW_THREADS
err = inflate(&(self->zst), Z_FINISH);
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 || err == Z_BUF_ERROR) && self->zst.avail_out == 0) {
if (_PyString_Resize(&retval, length << 1) < 0)
goto error;
self->zst.next_out = (Byte *)PyString_AS_STRING(retval) + length;
self->zst.avail_out = length;
length = length << 1;
Py_BEGIN_ALLOW_THREADS
err = inflate(&(self->zst), Z_FINISH);
Py_END_ALLOW_THREADS
}
/* If flushmode 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 */
if (err == Z_STREAM_END) {
err = inflateEnd(&(self->zst));
self->is_initialised = 0;
if (err != Z_OK) {
zlib_error(self->zst, err, "from inflateEnd()");
Py_DECREF(retval);
retval = NULL;
goto error;
}
}
_PyString_Resize(&retval, self->zst.total_out - start_total_out);
error:
LEAVE_ZLIB
return retval;
@ -868,6 +899,8 @@ PyInit_zlib(void)
if (ver != NULL)
PyModule_AddObject(m, "ZLIB_VERSION", ver);
PyModule_AddStringConstant(m, "__version__", "1.0");
#ifdef WITH_THREAD
zlib_lock = PyThread_allocate_lock();
#endif /* WITH_THREAD */