Commit f48f9d38 authored by Gregory P. Smith's avatar Gregory P. Smith

Force zlib.crc32 and zlib.adler32 to return a signed integer on all platforms

regardless of the native sizeof(long) used in the integer object.

This somewhat odd behavior of returning a signed is maintained in 2.x for
compatibility reasons of always returning an integer rather than a long object.

Fixes Issue1202 for Python 2.6
parent 33451d8a
......@@ -42,6 +42,12 @@ The available exception and functions in this module are:
the algorithm is designed for use as a checksum algorithm, it is not suitable
for use as a general hash algorithm.
This function always returns an integer object.
.. versionchanged:: 2.6
For consistent cross-platform behavior we always return a signed integer.
ie: Results in the (2**31)...(2**32-1) range will be negative.
.. function:: compress(string[, level])
......@@ -74,6 +80,12 @@ The available exception and functions in this module are:
the algorithm is designed for use as a checksum algorithm, it is not suitable
for use as a general hash algorithm.
This function always returns an integer object.
.. versionchanged:: 2.6
For consistent cross-platform behavior we always return a signed integer.
ie: Results in the (2**31)...(2**32-1) range will be negative.
.. function:: decompress(string[, wbits[, bufsize]])
......
......@@ -38,6 +38,15 @@ class ChecksumTestCase(unittest.TestCase):
self.assertEqual(zlib.crc32("penguin"), zlib.crc32("penguin", 0))
self.assertEqual(zlib.adler32("penguin"),zlib.adler32("penguin",1))
def test_abcdefghijklmnop(self):
"""test issue1202 compliance: signed crc32, adler32 in 2.x"""
foo = 'abcdefghijklmnop'
# explicitly test signed behavior
self.assertEqual(zlib.crc32(foo), -1808088941)
self.assertEqual(zlib.crc32('spam'), 1138425661)
self.assertEqual(zlib.adler32(foo+foo), -721416943)
self.assertEqual(zlib.adler32('spam'), 72286642)
class ExceptionTestCase(unittest.TestCase):
......
......@@ -27,6 +27,10 @@ Core and builtins
Library
-------
- Issue #1202: zlib.crc32 and zlib.adler32 no longer return different values
on 32-bit vs. 64-bit python interpreters. Both were correct, but they now
both return a signed integer object for consistency.
- Issue #1158: add %f format (fractions of a second represented as
microseconds) to datetime objects. Understood by both strptime and
strftime.
......
......@@ -884,37 +884,46 @@ 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.");
"a signed integer.");
static PyObject *
PyZlib_adler32(PyObject *self, PyObject *args)
{
uLong adler32val = adler32(0L, Z_NULL, 0);
Byte *buf;
int len;
int len, signed_val;
if (!PyArg_ParseTuple(args, "s#|k:adler32", &buf, &len, &adler32val))
return NULL;
adler32val = adler32(adler32val, buf, len);
return PyInt_FromLong(adler32val);
/* In Python 2.x we return a signed integer regardless of native platform
* long size (the 32bit unsigned long is treated as 32-bit signed and sign
* extended into a 64-bit long inside the integer object). 3.0 does the
* right thing and returns unsigned. http://bugs.python.org/issue1202 */
signed_val = adler32(adler32val, buf, len);
return PyInt_FromLong(signed_val);
}
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.");
"a signed integer.");
static PyObject *
PyZlib_crc32(PyObject *self, PyObject *args)
{
uLong crc32val = crc32(0L, Z_NULL, 0);
Byte *buf;
int len;
int len, signed_val;
if (!PyArg_ParseTuple(args, "s#|k:crc32", &buf, &len, &crc32val))
return NULL;
crc32val = crc32(crc32val, buf, len);
return PyInt_FromLong(crc32val);
/* In Python 2.x we return a signed integer regardless of native platform
* long size (the 32bit unsigned long is treated as 32-bit signed and sign
* extended into a 64-bit long inside the integer object). 3.0 does the
* right thing and returns unsigned. http://bugs.python.org/issue1202 */
signed_val = crc32(crc32val, buf, len);
return PyInt_FromLong(signed_val);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment