[pypy-commit] pypy stdlib-2.7.6: clean up select overflow checking

bdkearns noreply at buildbot.pypy.org
Sun Mar 2 16:29:49 CET 2014


Author: Brian Kearns <bdkearns at gmail.com>
Branch: stdlib-2.7.6
Changeset: r69615:5b6d13a5d362
Date: 2014-03-02 10:29 -0500
http://bitbucket.org/pypy/pypy/changeset/5b6d13a5d362/

Log:	clean up select overflow checking

diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -7,7 +7,8 @@
 from rpython.rlib.objectmodel import (we_are_translated, newlist_hint,
      compute_unique_id)
 from rpython.rlib.signature import signature
-from rpython.rlib.rarithmetic import r_uint
+from rpython.rlib.rarithmetic import r_uint, SHRT_MIN, SHRT_MAX, \
+    INT_MIN, INT_MAX, UINT_MAX
 
 from pypy.interpreter.executioncontext import (ExecutionContext, ActionFlag,
     UserDelAction)
@@ -18,8 +19,6 @@
 
 __all__ = ['ObjSpace', 'OperationError', 'W_Root']
 
-UINT_MAX_32_BITS = r_uint(4294967295)
-
 unpackiterable_driver = jit.JitDriver(name='unpackiterable',
                                       greens=['tp'],
                                       reds=['items', 'w_iterator'])
@@ -1466,7 +1465,7 @@
         # Like space.gateway_int_w(), but raises an app-level OverflowError if
         # the integer does not fit in 32 bits.  Here for gateway.py.
         value = self.gateway_int_w(w_obj)
-        if value < -2147483647-1 or value > 2147483647:
+        if value < INT_MIN or value > INT_MAX:
             raise OperationError(self.w_OverflowError,
                                  self.wrap("expected a 32-bit integer"))
         return value
@@ -1475,7 +1474,7 @@
         # Like space.gateway_uint_w(), but raises an app-level OverflowError if
         # the integer does not fit in 32 bits.  Here for gateway.py.
         value = self.uint_w(w_obj)
-        if value > UINT_MAX_32_BITS:
+        if value > UINT_MAX:
             raise OperationError(self.w_OverflowError,
                               self.wrap("expected an unsigned 32-bit integer"))
         return value
@@ -1488,11 +1487,21 @@
         if value < 0:
             raise OperationError(self.w_ValueError,
                                  self.wrap("expected a non-negative integer"))
-        if value > 2147483647:
+        if value > INT_MAX:
             raise OperationError(self.w_OverflowError,
                                  self.wrap("expected a 32-bit integer"))
         return value
 
+    def c_short_w(self, w_obj):
+        value = self.int_w(w_obj)
+        if value < SHRT_MIN:
+            raise oefmt(self.w_OverflowError,
+                "signed short integer is less than minimum")
+        elif value > SHRT_MAX:
+            raise oefmt(self.w_OverflowError,
+                "signed short integer is greater than maximum")
+        return value
+
     def truncatedint_w(self, w_obj, allow_conversion=True):
         # Like space.gateway_int_w(), but return the integer truncated
         # instead of raising OverflowError.  For obscure cases only.
diff --git a/pypy/interpreter/gateway.py b/pypy/interpreter/gateway.py
--- a/pypy/interpreter/gateway.py
+++ b/pypy/interpreter/gateway.py
@@ -147,6 +147,9 @@
     def visit_c_nonnegint(self, el, app_sig):
         self.checked_space_method(el, app_sig)
 
+    def visit_c_short(self, el, app_sig):
+        self.checked_space_method(el, app_sig)
+
     def visit_truncatedint_w(self, el, app_sig):
         self.checked_space_method(el, app_sig)
 
@@ -261,6 +264,9 @@
     def visit_c_nonnegint(self, typ):
         self.run_args.append("space.c_nonnegint_w(%s)" % (self.scopenext(),))
 
+    def visit_c_short(self, typ):
+        self.run_args.append("space.c_short_w(%s)" % (self.scopenext(),))
+
     def visit_truncatedint_w(self, typ):
         self.run_args.append("space.truncatedint_w(%s)" % (self.scopenext(),))
 
@@ -397,6 +403,9 @@
     def visit_c_nonnegint(self, typ):
         self.unwrap.append("space.c_nonnegint_w(%s)" % (self.nextarg(),))
 
+    def visit_c_short(self, typ):
+        self.unwrap.append("space.c_short_w(%s)" % (self.nextarg(),))
+
     def visit_truncatedint_w(self, typ):
         self.unwrap.append("space.truncatedint_w(%s)" % (self.nextarg(),))
 
diff --git a/pypy/module/select/interp_select.py b/pypy/module/select/interp_select.py
--- a/pypy/module/select/interp_select.py
+++ b/pypy/module/select/interp_select.py
@@ -1,7 +1,7 @@
 from pypy.interpreter.typedef import TypeDef
 from pypy.interpreter.baseobjspace import W_Root
 from pypy.interpreter.gateway import interp2app, unwrap_spec, WrappedDefault
-from pypy.interpreter.error import OperationError, wrap_oserror
+from pypy.interpreter.error import OperationError, wrap_oserror, oefmt
 from rpython.rlib import rpoll
 import errno
 
@@ -20,12 +20,8 @@
     def __init__(self):
         self.fddict = {}
 
-    @unwrap_spec(events=int)
+    @unwrap_spec(events="c_short")
     def register(self, space, w_fd, events=defaultevents):
-        if not -32767 - 1 <= events <= 32767:
-            m = ("signed short integer is " +
-                 "greater than maximum" if events > 0 else "less than minimum")
-            raise OperationError(space.w_OverflowError, space.wrap(m))
         fd = space.c_filedescriptor_w(w_fd)
         self.fddict[fd] = events
 
@@ -53,15 +49,11 @@
             # we want to be compatible with cpython and also accept things
             # that can be casted to integer (I think)
             try:
-                # compute the integer
-                timeout = space.int_w(space.int(w_timeout))
-            except (OverflowError, ValueError):
-                raise OperationError(space.w_ValueError,
-                                     space.wrap("math range error"))
-
-        if not -2147483647 - 1 <= timeout <= 2147483647:
-            msg = "Python int too large to convert to C int"
-            raise OperationError(space.w_OverflowError, space.wrap(msg))
+                w_timeout = space.int(w_timeout)
+            except OperationError:
+                raise oefmt(space.w_TypeError,
+                    "timeout must be an integer or None")
+            timeout = space.c_int_w(w_timeout)
 
         try:
             retval = rpoll.poll(self.fddict, timeout)
diff --git a/pypy/module/select/test/test_select.py b/pypy/module/select/test/test_select.py
--- a/pypy/module/select/test/test_select.py
+++ b/pypy/module/select/test/test_select.py
@@ -213,7 +213,7 @@
             readend.close()
             writeend.close()
 
-    def test_poll_int_overflow(self):
+    def test_poll_int_arguments(self):
         import select
 
         pollster = select.poll()
@@ -222,12 +222,16 @@
         raises(OverflowError, pollster.poll, 1L << 64)
 
         pollster = select.poll()
-        raises(OverflowError, pollster.register, 0, 32768) # SHRT_MAX + 1
-        raises(OverflowError, pollster.register, 0, -32768 - 1)
+        exc = raises(OverflowError, pollster.register, 0, 32768) # SHRT_MAX + 1
+        assert exc.value[0] == 'signed short integer is greater than maximum'
+        exc = raises(OverflowError, pollster.register, 0, -32768 - 1)
+        assert exc.value[0] == 'signed short integer is less than minimum'
         raises(OverflowError, pollster.register, 0, 65535) # USHRT_MAX + 1
         raises(OverflowError, pollster.poll, 2147483648) # INT_MAX +  1
         raises(OverflowError, pollster.poll, -2147483648 - 1)
         raises(OverflowError, pollster.poll, 4294967296) # UINT_MAX + 1
+        exc = raises(TypeError, pollster.poll, '123')
+        assert exc.value[0] == 'timeout must be an integer or None'
 
 
 class AppTestSelectWithPipes(_AppTestSelect):
diff --git a/rpython/rlib/rarithmetic.py b/rpython/rlib/rarithmetic.py
--- a/rpython/rlib/rarithmetic.py
+++ b/rpython/rlib/rarithmetic.py
@@ -75,7 +75,11 @@
 # to handle the win64 special case:
 is_emulated_long = _long_typecode != 'l'
 
+SHRT_MIN = -2**(_get_bitsize('h') - 1)
+SHRT_MAX = 2**(_get_bitsize('h') - 1) - 1
+INT_MIN = -2**(_get_bitsize('i') - 1)
 INT_MAX = 2**(_get_bitsize('i') - 1) - 1
+UINT_MAX = 2**_get_bitsize('i') - 1
 
 LONG_BIT = _get_long_bit()
 LONG_MASK = (2**LONG_BIT)-1


More information about the pypy-commit mailing list