Author: Armin Rigo <[email protected]>
Branch:
Changeset: r3283:f34ec7d90cd6
Date: 2019-07-23 06:37 +0200
http://bitbucket.org/cffi/cffi/changeset/f34ec7d90cd6/
Log: Issue #413
Test and "fix" for a corner case: now it gives a RuntimeError with a
message, instead of a C-level infinite recursion
diff --git a/c/realize_c_type.c b/c/realize_c_type.c
--- a/c/realize_c_type.c
+++ b/c/realize_c_type.c
@@ -413,19 +413,12 @@
}
static PyObject *
-realize_c_type_or_func(builder_c_t *builder,
- _cffi_opcode_t opcodes[], int index)
+realize_c_type_or_func_now(builder_c_t *builder, _cffi_opcode_t op,
+ _cffi_opcode_t opcodes[], int index)
{
PyObject *x, *y, *z;
- _cffi_opcode_t op = opcodes[index];
Py_ssize_t length = -1;
- if ((((uintptr_t)op) & 1) == 0) {
- x = (PyObject *)op;
- Py_INCREF(x);
- return x;
- }
-
switch (_CFFI_GETOP(op)) {
case _CFFI_OP_PRIMITIVE:
@@ -638,11 +631,40 @@
break;
}
+ case 255: /* recursion detection */
+ PyErr_Format(PyExc_RuntimeError,
+ "found a situation in which we try to build a type recursively. "
+ "This is known to occur e.g. in ``struct s { void(*callable)"
+ "(struct s); }''. Please report if you get this error and "
+ "really need support for your case.");
+ return NULL;
+
default:
PyErr_Format(PyExc_NotImplementedError, "op=%d", (int)_CFFI_GETOP(op));
return NULL;
}
+ return x;
+}
+
+static PyObject *
+realize_c_type_or_func(builder_c_t *builder,
+ _cffi_opcode_t opcodes[], int index)
+{
+ PyObject *x;
+ _cffi_opcode_t op = opcodes[index];
+
+ if ((((uintptr_t)op) & 1) == 0) {
+ x = (PyObject *)op;
+ Py_INCREF(x);
+ return x;
+ }
+
+ opcodes[index] = (_cffi_opcode_t)255; /* recursion detection */
+ x = realize_c_type_or_func_now(builder, op, opcodes, index);
+ if (opcodes[index] == (_cffi_opcode_t)255)
+ opcodes[index] = op;
+
if (x != NULL && opcodes == builder->ctx.types && opcodes[index] != x) {
assert((((uintptr_t)x) & 1) == 0);
assert((((uintptr_t)opcodes[index]) & 1) == 1);
@@ -650,7 +672,7 @@
opcodes[index] = x;
}
return x;
-};
+}
static CTypeDescrObject *
realize_c_func_return_type(builder_c_t *builder,
diff --git a/testing/cffi1/test_recompiler.py b/testing/cffi1/test_recompiler.py
--- a/testing/cffi1/test_recompiler.py
+++ b/testing/cffi1/test_recompiler.py
@@ -2412,3 +2412,15 @@
a = ffi.new("struct A *")
assert ffi.sizeof(a[0]) == ffi.sizeof("unsigned")
assert ffi.sizeof(b[0]) == ffi.sizeof(a[0])
+
+def test_struct_with_func_with_struct_arg():
+ ffi = FFI()
+ ffi.cdef("""struct BinaryTree {
+ int (* CompareKey)(struct BinaryTree tree);
+ };""")
+ lib = verify(ffi, "test_struct_with_func_with_struct_arg", """
+ struct BinaryTree {
+ int (* CompareKey)(struct BinaryTree tree);
+ };
+ """)
+ py.test.raises(RuntimeError, ffi.new, "struct BinaryTree *")
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit