summaryrefslogtreecommitdiff
path: root/c
diff options
context:
space:
mode:
authorArmin Rigo <arigo@tunes.org>2019-07-23 06:37:23 +0200
committerArmin Rigo <arigo@tunes.org>2019-07-23 06:37:23 +0200
commit54bce94ce51fac430be31a509fc83e55faa9b30d (patch)
treea3755e65caa0579e6f165986be6706c3226281f9 /c
parent1e23dd09b5466a10ee2d4cf313689c1f9d90b36b (diff)
downloadcffi-54bce94ce51fac430be31a509fc83e55faa9b30d.tar.gz
Issue #413
Test and "fix" for a corner case: now it gives a RuntimeError with a message, instead of a C-level infinite recursion
Diffstat (limited to 'c')
-rw-r--r--c/realize_c_type.c42
1 files changed, 32 insertions, 10 deletions
diff --git a/c/realize_c_type.c b/c/realize_c_type.c
index 082c488..778f320 100644
--- a/c/realize_c_type.c
+++ b/c/realize_c_type.c
@@ -413,19 +413,12 @@ _realize_c_struct_or_union(builder_c_t *builder, int sindex)
}
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 @@ realize_c_type_or_func(builder_c_t *builder,
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 @@ realize_c_type_or_func(builder_c_t *builder,
opcodes[index] = x;
}
return x;
-};
+}
static CTypeDescrObject *
realize_c_func_return_type(builder_c_t *builder,