diff options
author | Armin Rigo <arigo@tunes.org> | 2019-07-23 06:37:23 +0200 |
---|---|---|
committer | Armin Rigo <arigo@tunes.org> | 2019-07-23 06:37:23 +0200 |
commit | 54bce94ce51fac430be31a509fc83e55faa9b30d (patch) | |
tree | a3755e65caa0579e6f165986be6706c3226281f9 /c | |
parent | 1e23dd09b5466a10ee2d4cf313689c1f9d90b36b (diff) | |
download | cffi-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.c | 42 |
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, |