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