cpython: 80f6f77a7cc3 (original) (raw)

Mercurial > cpython

changeset 99257:80f6f77a7cc3 3.5

Issue #25626: Change zlib to accept Py_ssize_t and cap to UINT_MAX The underlying zlib library stores sizes in “unsigned int”. The corresponding Python parameters are all sizes of buffers filled in by zlib, so it is okay to reduce higher values to the UINT_MAX internal cap. OverflowError is still raised for sizes that do not fit in Py_ssize_t. Sizes are now limited to Py_ssize_t rather than unsigned long, because Python byte strings cannot be larger than Py_ssize_t. Previously this could result in a SystemError on 32-bit platforms. This resolves a regression in the gzip module when reading more than UINT_MAX or LONG_MAX bytes in one call, introduced by revision 62723172412c. [#25626]

Martin Panter vadmium+py@gmail.com
date Fri, 20 Nov 2015 08:13:35 +0000
parents c3cc5d70a6bf
children afa1b6cd77a5 df11d58fce00
files Doc/howto/clinic.rst Lib/test/support/__init__.py Lib/test/test_gzip.py Lib/test/test_zlib.py Misc/NEWS Modules/clinic/zlibmodule.c.h Modules/zlibmodule.c
diffstat 7 files changed, 120 insertions(+), 47 deletions(-)[+] [-] Doc/howto/clinic.rst 16 Lib/test/support/__init__.py 13 Lib/test/test_gzip.py 9 Lib/test/test_zlib.py 56 Misc/NEWS 7 Modules/clinic/zlibmodule.c.h 8 Modules/zlibmodule.c 58

line wrap: on

line diff

--- a/Doc/howto/clinic.rst +++ b/Doc/howto/clinic.rst @@ -1249,18 +1249,18 @@ Here's the simplest example of a custom /*[python input]

[python start generated code]*/

-This block adds a converter to Argument Clinic named uint. Parameters -declared as uint will be declared as type unsigned int, and will -be parsed by the 'O&' format unit, which will call the uint_converter -converter function. -uint variables automatically support default values. +This block adds a converter to Argument Clinic named capped_uint. Parameters +declared as capped_uint will be declared as type unsigned int, and will +be parsed by the 'O&' format unit, which will call the +capped_uint_converter converter function. capped_uint variables +automatically support default values. More sophisticated custom converters can insert custom C code to handle initialization and cleanup.

--- a/Lib/test/support/init.py +++ b/Lib/test/support/init.py @@ -1608,12 +1608,15 @@ class _MemoryWatchdog: def bigmemtest(size, memuse, dry_run=True): """Decorator for bigmem tests.

--- a/Lib/test/test_gzip.py +++ b/Lib/test/test_gzip.py @@ -3,6 +3,7 @@ import unittest from test import support +from test.support import bigmemtest, _4G import os import io import struct @@ -116,6 +117,14 @@ class TestGzip(BaseTest): self.assertEqual(f.tell(), nread) self.assertEqual(b''.join(blocks), data1 * 50)

+ def test_io_on_closed_object(self): # Test that I/O operations on closed GzipFile objects raise a # ValueError, just like the corresponding functions on file objects.

--- a/Lib/test/test_zlib.py +++ b/Lib/test/test_zlib.py @@ -122,11 +122,17 @@ class ExceptionTestCase(unittest.TestCas self.assertRaises(ValueError, zlib.decompressobj().flush, 0) self.assertRaises(ValueError, zlib.decompressobj().flush, -1)

+ class BaseCompressTestCase(object): def check_big_compress_buffer(self, size, compress_func): _1M = 1024 * 1024

@@ -196,6 +202,18 @@ class CompressTestCase(BaseCompressTestC finally: data = None

+

+ class CompressObjectTestCase(BaseCompressTestCase, unittest.TestCase): # Test compression object @@ -364,6 +382,21 @@ class CompressObjectTestCase(BaseCompres self.assertRaises(ValueError, dco.decompress, b"", -1) self.assertEqual(b'', dco.unconsumed_tail)

+

+ def test_clear_unconsumed_tail(self): # Issue #12050: calling decompress() without providing max_length # should clear the unconsumed_tail attribute. @@ -537,6 +570,22 @@ class CompressObjectTestCase(BaseCompres data = zlib.compress(input2) self.assertEqual(dco.flush(), input1[1:])

+

+ @requires_Compress_copy def test_compresscopy(self): # Test copying a compression object @@ -725,5 +774,10 @@ LAERTES """ +class CustomInt:

+ + if name == "main": unittest.main()

--- a/Misc/NEWS +++ b/Misc/NEWS @@ -77,6 +77,13 @@ Core and Builtins Library ------- +- Issue #25626: Change three zlib functions to accept sizes that fit in

--- a/Modules/clinic/zlibmodule.c.h +++ b/Modules/clinic/zlibmodule.c.h @@ -68,7 +68,7 @@ zlib_decompress(PyModuleDef module, PyO unsigned int bufsize = DEF_BUF_SIZE; if (!PyArg_ParseTuple(args, "y|iO&:decompress",

#ifndef ZLIB_COMPRESS_COPY_METHODDEF #define ZLIB_COMPRESS_COPY_METHODDEF #endif /* !defined(ZLIB_COMPRESS_COPY_METHODDEF) / -/[clinic end generated code: output=56ed1147bbbb4788 input=a9049054013a1b77]/ +/[clinic end generated code: output=7734aec079550bc8 input=a9049054013a1b77]*/

--- a/Modules/zlibmodule.c +++ b/Modules/zlibmodule.c @@ -226,42 +226,42 @@ zlib_compress_impl(PyModuleDef module, /[python input] -class uint_converter(CConverter): +class capped_uint_converter(CConverter): type = 'unsigned int'

@@ -272,7 +272,7 @@ zlib.decompress Compressed data. wbits: int(c_default="MAX_WBITS") = MAX_WBITS The window buffer size.

-/[clinic end generated code: output=444d0987f3429574 input=0f4b9abb7103f50e]/ +/[clinic end generated code: output=444d0987f3429574 input=da095118b3243b27]/ { PyObject *result_str = NULL; Byte *input; @@ -691,7 +691,7 @@ zlib.Decompress.decompress data: Py_buffer The binary data to decompress.

@@ -707,7 +707,7 @@ Call the flush() method to clear these b static PyObject zlib_Decompress_decompress_impl(compobject self, Py_buffer data, unsigned int max_length) -/[clinic end generated code: output=b82e2a2c19f5fe7b input=02cfc047377cec86]/ +/[clinic end generated code: output=b82e2a2c19f5fe7b input=68b6508ab07c2cf0]/ { int err; unsigned int old_length, length = DEF_BUF_SIZE; @@ -1048,7 +1048,7 @@ error: /[clinic input] zlib.Decompress.flush