[pypy-commit] pypy default: ensure __len__() is under sys.maxsize

gutworth noreply at buildbot.pypy.org
Tue May 24 22:32:41 CEST 2011


Author: Benjamin Peterson <benjamin at python.org>
Branch: 
Changeset: r44412:1df2c9bafc4e
Date: 2011-05-24 15:40 -0500
http://bitbucket.org/pypy/pypy/changeset/1df2c9bafc4e/

Log:	ensure __len__() is under sys.maxsize

diff --git a/pypy/objspace/descroperation.py b/pypy/objspace/descroperation.py
--- a/pypy/objspace/descroperation.py
+++ b/pypy/objspace/descroperation.py
@@ -236,8 +236,19 @@
         else:
             return self.w_False
 
-##    def len(self, w_obj):
-##        XXX needs to check that the result is an int (or long?) >= 0
+    def len(space, w_obj):
+        w_descr = space.lookup(w_obj, '__len__')
+        if w_descr is None:
+            name = space.type(w_obj).getname(space)
+            msg = "'%s' has no length" % (name,)
+            raise OperationError(space.w_TypeError, space.wrap(msg))
+        w_res = space.get_and_call_function(w_descr, w_obj)
+        space._check_len_result(w_res)
+        return w_res
+
+    def _check_len_result(space, w_obj):
+        # Will complain if result is too big.
+        space.int_w(w_obj)
 
     def iter(space, w_obj):
         w_descr = space.lookup(w_obj, '__iter__')
diff --git a/pypy/objspace/std/objspace.py b/pypy/objspace/std/objspace.py
--- a/pypy/objspace/std/objspace.py
+++ b/pypy/objspace/std/objspace.py
@@ -448,6 +448,10 @@
     def is_w(self, w_one, w_two):
         return w_one is w_two
 
+    def _check_len_result(self, w_obj):
+        if type(w_obj) is not W_IntObject:
+            DescrOperation._check_len_result(self, w_obj)
+
     def is_true(self, w_obj):
         # a shortcut for performance
         # NOTE! this method is typically overridden by builtinshortcut.py.
diff --git a/pypy/objspace/test/test_descroperation.py b/pypy/objspace/test/test_descroperation.py
--- a/pypy/objspace/test/test_descroperation.py
+++ b/pypy/objspace/test/test_descroperation.py
@@ -532,5 +532,12 @@
         del X.__nonzero__
         assert X()
 
+    def test_len_overflow(self):
+        import sys
+        class X(object):
+            def __len__(self):
+                return sys.maxsize + 1
+        raises(OverflowError, len, X())
+
 class AppTestWithBuiltinShortcut(AppTest_Descroperation):
     OPTIONS = {'objspace.std.builtinshortcut': True}


More information about the pypy-commit mailing list