[pypy-commit] pypy default: On CPython, some functions accept integers of any size and

arigo noreply at buildbot.pypy.org
Sat Jul 23 11:00:28 CEST 2011


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r45894:48020b9e373b
Date: 2011-07-23 11:00 +0200
http://bitbucket.org/pypy/pypy/changeset/48020b9e373b/

Log:	On CPython, some functions accept integers of any size and truncate.
	This seems to be important at least for crc32() and adler32(), so
	fix it for them.

diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -1284,6 +1284,17 @@
                                  self.wrap("expected a 32-bit integer"))
         return value
 
+    def truncatedint(self, w_obj):
+        # Like space.gateway_int_w(), but return the integer truncated
+        # instead of raising OverflowError.  For obscure cases only.
+        try:
+            return self.int_w(w_obj)
+        except OperationError, e:
+            if not e.match(self, self.w_OverflowError):
+                raise
+            from pypy.rlib.rarithmetic import intmask
+            return intmask(self.bigint_w(w_obj).uintmask())
+
     def c_filedescriptor_w(self, w_fd):
         # This is only used sometimes in CPython, e.g. for os.fsync() but
         # not os.close().  It's likely designed for 'select'.  It's irregular
diff --git a/pypy/interpreter/gateway.py b/pypy/interpreter/gateway.py
--- a/pypy/interpreter/gateway.py
+++ b/pypy/interpreter/gateway.py
@@ -140,6 +140,9 @@
     def visit_c_nonnegint(self, el, app_sig):
         self.checked_space_method(el, app_sig)
 
+    def visit_truncatedint(self, el, app_sig):
+        self.checked_space_method(el, app_sig)
+
     def visit__Wrappable(self, el, app_sig):
         name = el.__name__
         argname = self.orig_arg()
@@ -257,6 +260,9 @@
     def visit_c_nonnegint(self, typ):
         self.run_args.append("space.c_nonnegint_w(%s)" % (self.scopenext(),))
 
+    def visit_truncatedint(self, typ):
+        self.run_args.append("space.truncatedint(%s)" % (self.scopenext(),))
+
     def _make_unwrap_activation_class(self, unwrap_spec, cache={}):
         try:
             key = tuple(unwrap_spec)
@@ -387,6 +393,9 @@
     def visit_c_nonnegint(self, typ):
         self.unwrap.append("space.c_nonnegint_w(%s)" % (self.nextarg(),))
 
+    def visit_truncatedint(self, typ):
+        self.unwrap.append("space.truncatedint(%s)" % (self.nextarg(),))
+
     def make_fastfunc(unwrap_spec, func):
         unwrap_info = UnwrapSpec_FastFunc_Unwrap()
         unwrap_info.apply_over(unwrap_spec)
diff --git a/pypy/module/binascii/interp_crc32.py b/pypy/module/binascii/interp_crc32.py
--- a/pypy/module/binascii/interp_crc32.py
+++ b/pypy/module/binascii/interp_crc32.py
@@ -61,7 +61,7 @@
 crc_32_tab = map(r_uint, crc_32_tab)
 
 
- at unwrap_spec(data='bufferstr', oldcrc='c_int')
+ at unwrap_spec(data='bufferstr', oldcrc='truncatedint')
 def crc32(space, data, oldcrc=0):
     "Compute the CRC-32 incrementally."
 
diff --git a/pypy/module/binascii/test/test_binascii.py b/pypy/module/binascii/test/test_binascii.py
--- a/pypy/module/binascii/test/test_binascii.py
+++ b/pypy/module/binascii/test/test_binascii.py
@@ -374,6 +374,8 @@
             ('x', 10000, -1855256896),
             ('y', 10000, -429115818),
             ('z', 10000, 2137352172),
+            ('foo', 99999999999999999999999999, -1932704816),
+            ('bar', -99999999999999999999999999, 2000545409),
             ]:
             assert self.binascii.crc32(input, initial) == expected
 
diff --git a/pypy/module/zlib/interp_zlib.py b/pypy/module/zlib/interp_zlib.py
--- a/pypy/module/zlib/interp_zlib.py
+++ b/pypy/module/zlib/interp_zlib.py
@@ -20,25 +20,15 @@
         return intmask((x ^ SIGN_EXTEND2) - SIGN_EXTEND2)
 
 
- at unwrap_spec(string='bufferstr')
-def crc32(space, string, w_start = rzlib.CRC32_DEFAULT_START):
+ at unwrap_spec(string='bufferstr', start='truncatedint')
+def crc32(space, string, start = rzlib.CRC32_DEFAULT_START):
     """
     crc32(string[, start]) -- Compute a CRC-32 checksum of string.
 
     An optional starting value can be specified.  The returned checksum is
     an integer.
     """
-    if space.is_true(space.isinstance(w_start, space.w_long)):
-        num = space.bigint_w(w_start)
-        ustart = num.uintmask()
-    elif space.is_true(space.isinstance(w_start, space.w_int)):
-        start = space.int_w(w_start)
         ustart = r_uint(start)
-    else:
-        raise OperationError(space.w_TypeError,
-                             space.wrap("crc32() argument 2 must "
-                                        "be integer<k>, not str"))
-
     checksum = rzlib.crc32(string, ustart)
 
     # This is, perhaps, a little stupid.  zlib returns the checksum unsigned.
@@ -51,7 +41,7 @@
     return space.wrap(checksum)
 
 
- at unwrap_spec(string='bufferstr', start=r_uint)
+ at unwrap_spec(string='bufferstr', start='truncatedint')
 def adler32(space, string, start=rzlib.ADLER32_DEFAULT_START):
     """
     adler32(string[, start]) -- Compute an Adler-32 checksum of string.
@@ -59,7 +49,8 @@
     An optional starting value can be specified.  The returned checksum is
     an integer.
     """
-    checksum = rzlib.adler32(string, start)
+    ustart = r_uint(start)
+    checksum = rzlib.adler32(string, ustart)
     # See comments in crc32() for the following line
     checksum = unsigned_to_signed_32bit(checksum)
 
diff --git a/pypy/module/zlib/test/test_zlib.py b/pypy/module/zlib/test/test_zlib.py
--- a/pypy/module/zlib/test/test_zlib.py
+++ b/pypy/module/zlib/test/test_zlib.py
@@ -78,15 +78,17 @@
     def test_crc32_negative_long_start(self):
         v = self.zlib.crc32('', -1L)
         assert v == -1
+        assert self.zlib.crc32('foo', -99999999999999999999999) == 1611238463
 
     def test_crc32_long_start(self):
         import sys
         v = self.zlib.crc32('', sys.maxint*2)
         assert v == -2
+        assert self.zlib.crc32('foo', 99999999999999999999999) == 1635107045
 
     def test_adler32(self):
         """
-        When called with a string, zlib.crc32 should compute its adler 32
+        When called with a string, zlib.adler32() should compute its adler 32
         checksum and return it as a signed 32 bit integer.
         On 64-bit machines too
         (it is a bug in CPython < 2.6 to return unsigned values in this case).
@@ -113,6 +115,9 @@
         helloworldsum = self.zlib.adler32(world, hellosum)
         assert helloworldsum == self.zlib.adler32(hello + world)
 
+        assert self.zlib.adler32('foo', -1) == 45547858
+        assert self.zlib.adler32('foo', 99999999999999999999999) == -114818734
+
 
     def test_invalidLevel(self):
         """


More information about the pypy-commit mailing list