From cd9d2b2a3611f23f4c044c3e2a1f852583e078f7 Mon Sep 17 00:00:00 2001 From: Stefan Behnel Date: Sun, 26 Dec 2010 22:34:22 +0100 Subject: [PATCH] fix bug 633: make sure we own references to Python arguments passed into C functions --- Cython/Compiler/ExprNodes.py | 9 ++++++++- tests/run/owned_arg_refs.pyx | 28 ++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 tests/run/owned_arg_refs.pyx diff --git a/Cython/Compiler/ExprNodes.py b/Cython/Compiler/ExprNodes.py index c0440641..8aead92c 100755 --- a/Cython/Compiler/ExprNodes.py +++ b/Cython/Compiler/ExprNodes.py @@ -2953,7 +2953,14 @@ class SimpleCallNode(CallNode): # Coerce arguments for i in range(min(max_nargs, actual_nargs)): formal_type = func_type.args[i].type - self.args[i] = self.args[i].coerce_to(formal_type, env) + arg = self.args[i].coerce_to(formal_type, env) + if arg.is_attribute or not arg.is_simple: + # we do not own the argument's reference, but we must + # make sure it cannot be collected before we return + # from the function, so we create an owned temp + # reference to it + arg = arg.coerce_to_temp(env) + self.args[i] = arg for i in range(max_nargs, actual_nargs): if self.args[i].type.is_pyobject: error(self.args[i].pos, diff --git a/tests/run/owned_arg_refs.pyx b/tests/run/owned_arg_refs.pyx new file mode 100644 index 00000000..5bf84d76 --- /dev/null +++ b/tests/run/owned_arg_refs.pyx @@ -0,0 +1,28 @@ + +cdef class Owner: + cdef object x + +cdef call_me_with_owner(Owner owner, x): + owner.x = "def" # overwrite external reference + return x # crashes if x is not owned by function or caller + +def test_ext_type_attr(): + """ + >>> test_ext_type_attr() + 'abc5' + """ + owner = Owner() + owner.x = ''.join("abc%d" % 5) # non-interned object + return call_me_with_owner(owner, owner.x) + +cdef call_me_with_list(list l, x): + l[:] = [(1,2), (3,4)] # overwrite external reference + return x # crashes if x is not owned by function or caller + +def test_index(): + """ + >>> test_index() + [3, 4] + """ + l = [[1,2],[3,4]] + return call_me_with_list(l, l[1]) -- 2.26.2