Author: Armin Rigo <[email protected]>
Branch: 
Changeset: r83434:94bf747cee5d
Date: 2016-03-30 13:05 +0200
http://bitbucket.org/pypy/pypy/changeset/94bf747cee5d/

Log:    Issue #2266: check that PyTupleObjects do not contain any NULLs at
        the point of conversion to W_TupleObjects.

diff --git a/pypy/module/cpyext/test/test_sequence.py 
b/pypy/module/cpyext/test/test_sequence.py
--- a/pypy/module/cpyext/test/test_sequence.py
+++ b/pypy/module/cpyext/test/test_sequence.py
@@ -90,8 +90,10 @@
         self.raises(space, api, IndexError, api.PySequence_SetItem,
                     l, 3, w_value)
 
+        t = api.PyTuple_New(1)
+        api.PyTuple_SetItem(t, 0, l)
         self.raises(space, api, TypeError, api.PySequence_SetItem,
-                    api.PyTuple_New(1), 0, w_value)
+                    t, 0, w_value)
 
         self.raises(space, api, TypeError, api.PySequence_SetItem,
                     space.newdict(), 0, w_value)
diff --git a/pypy/module/cpyext/test/test_tupleobject.py 
b/pypy/module/cpyext/test/test_tupleobject.py
--- a/pypy/module/cpyext/test/test_tupleobject.py
+++ b/pypy/module/cpyext/test/test_tupleobject.py
@@ -5,6 +5,7 @@
 from pypy.module.cpyext.test.test_api import BaseApiTest
 from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
 from rpython.rtyper.lltypesystem import rffi, lltype
+from rpython.rlib.debug import FatalError
 
 
 class TestTupleObject(BaseApiTest):
@@ -18,29 +19,44 @@
         #assert api.PyTuple_GET_SIZE(atuple) == 3  --- now a C macro
         raises(TypeError, api.PyTuple_Size(space.newlist([])))
         api.PyErr_Clear()
-    
+
+    def test_tuple_realize_refuses_nulls(self, space, api):
+        py_tuple = api.PyTuple_New(1)
+        py.test.raises(FatalError, from_ref, space, py_tuple)
+
     def test_tuple_resize(self, space, api):
         w_42 = space.wrap(42)
+        w_43 = space.wrap(43)
+        w_44 = space.wrap(44)
         ar = lltype.malloc(PyObjectP.TO, 1, flavor='raw')
 
         py_tuple = api.PyTuple_New(3)
         # inside py_tuple is an array of "PyObject *" items which each hold
         # a reference
         rffi.cast(PyTupleObject, py_tuple).c_ob_item[0] = make_ref(space, w_42)
+        rffi.cast(PyTupleObject, py_tuple).c_ob_item[1] = make_ref(space, w_43)
         ar[0] = py_tuple
         api._PyTuple_Resize(ar, 2)
         w_tuple = from_ref(space, ar[0])
         assert space.int_w(space.len(w_tuple)) == 2
         assert space.int_w(space.getitem(w_tuple, space.wrap(0))) == 42
+        assert space.int_w(space.getitem(w_tuple, space.wrap(1))) == 43
         api.Py_DecRef(ar[0])
 
         py_tuple = api.PyTuple_New(3)
         rffi.cast(PyTupleObject, py_tuple).c_ob_item[0] = make_ref(space, w_42)
+        rffi.cast(PyTupleObject, py_tuple).c_ob_item[1] = make_ref(space, w_43)
+        rffi.cast(PyTupleObject, py_tuple).c_ob_item[2] = make_ref(space, w_44)
         ar[0] = py_tuple
         api._PyTuple_Resize(ar, 10)
+        assert api.PyTuple_Size(ar[0]) == 10
+        for i in range(3, 10):
+            rffi.cast(PyTupleObject, py_tuple).c_ob_item[i] = make_ref(
+                space, space.wrap(42 + i))
         w_tuple = from_ref(space, ar[0])
         assert space.int_w(space.len(w_tuple)) == 10
-        assert space.int_w(space.getitem(w_tuple, space.wrap(0))) == 42
+        for i in range(10):
+            assert space.int_w(space.getitem(w_tuple, space.wrap(i))) == 42 + i
         api.Py_DecRef(ar[0])
 
         lltype.free(ar, flavor='raw')
diff --git a/pypy/module/cpyext/tupleobject.py 
b/pypy/module/cpyext/tupleobject.py
--- a/pypy/module/cpyext/tupleobject.py
+++ b/pypy/module/cpyext/tupleobject.py
@@ -1,5 +1,6 @@
 from pypy.interpreter.error import OperationError
 from rpython.rtyper.lltypesystem import rffi, lltype
+from rpython.rlib.debug import fatalerror_notb
 from pypy.module.cpyext.api import (cpython_api, Py_ssize_t, CANNOT_FAIL,
                                     build_type_checkers, PyObjectFields,
                                     cpython_struct, bootstrap_function)
@@ -91,14 +92,22 @@
 def tuple_realize(space, py_obj):
     """
     Creates the tuple in the interpreter. The PyTupleObject must not
-    be modified after this call.
+    be modified after this call.  We check that it does not contain
+    any NULLs at this point (which would correspond to half-broken
+    W_TupleObjects).
     """
     py_tup = rffi.cast(PyTupleObject, py_obj)
     l = py_tup.c_ob_size
     p = py_tup.c_ob_item
     items_w = [None] * l
     for i in range(l):
-        items_w[i] = from_ref(space, p[i])
+        w_item = from_ref(space, p[i])
+        if w_item is None:
+            fatalerror_notb(
+                "Fatal error in cpyext, CPython compatibility layer: "
+                "converting a PyTupleObject into a W_TupleObject, "
+                "but found NULLs as items")
+        items_w[i] = w_item
     w_obj = space.newtuple(items_w)
     track_reference(space, py_obj, w_obj)
     return w_obj
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to