Author: Matti Picus <[email protected]>
Branch: warn-no-ref-kept
Changeset: r2871:ce17083bac2b
Date: 2017-01-23 23:36 +0200
http://bitbucket.org/cffi/cffi/changeset/ce17083bac2b/
Log: proof-of-concept issue a warning if assigning a dead object to a
struct field
diff --git a/c/_cffi_backend.c b/c/_cffi_backend.c
--- a/c/_cffi_backend.c
+++ b/c/_cffi_backend.c
@@ -2503,6 +2503,13 @@
{
CFieldObject *cf;
CTypeDescrObject *ct = cd->c_type;
+ if (value && (CDataOwn_Check(value) || Py_TYPE(value) == &CDataGCP_Type)
&& (value->ob_refcnt == 1))
+ {
+ if (PyErr_WarnEx(PyExc_UserWarning,
+ "setting a struct field with a non-referenced value, expect
trouble", 1))
+ return -1;
+ }
+
if (ct->ct_flags & CT_POINTER)
ct = ct->ct_itemdescr;
diff --git a/testing/cffi0/test_ffi_backend.py
b/testing/cffi0/test_ffi_backend.py
--- a/testing/cffi0/test_ffi_backend.py
+++ b/testing/cffi0/test_ffi_backend.py
@@ -128,6 +128,27 @@
alloc5 = ffi.new_allocator(myalloc5)
py.test.raises(MemoryError, alloc5, "int[5]")
+ def test_no_ref_kept(self):
+ import gc, numpy as np
+ ffi = FFI(backend=self.Backend())
+ seen = []
+ def myalloc(size):
+ seen.append(size)
+ return ffi.new("char[]", b"X" * size)
+ def myfree(raw):
+ seen.append(raw)
+ ffi.cdef('typedef struct {char * buf;} vstruct;')
+ alloc = ffi.new_allocator(myalloc, myfree)
+ vstruct = ffi.new('vstruct[1]')
+ b = np.empty(10, dtype='uint8')
+ vstruct[0].buf = ffi.cast('char*', b.ctypes.data)
+ with pytest.warns(UserWarning):
+ vstruct[0].buf = alloc('char[]', chr(100) * 100)
+ for i in range(10):
+ gc.collect()
+ if len(seen) > 1:
+ break
+ assert len(seen) == 2
class TestBitfield:
def check(self, source, expected_ofs_y, expected_align, expected_size):
@@ -505,3 +526,5 @@
py.test.raises(TypeError, cd)
py.test.raises(TypeError, cd, ffi.NULL)
py.test.raises(TypeError, cd, ffi.typeof("void *"))
+
+
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit