Author: Armin Rigo <[email protected]>
Branch: 
Changeset: r3301:3873bbdd3b9e
Date: 2019-10-21 11:24 +0200
http://bitbucket.org/cffi/cffi/changeset/3873bbdd3b9e/

Log:    Issue #429

        There are corner cases in which we can see a recursion on the same
        types. Instead of fighting them all, change the logic to complain if
        we recurse more than 1000 times.

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
@@ -631,14 +631,6 @@
         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;
@@ -647,6 +639,8 @@
     return x;
 }
 
+static int _realize_recursion_level;
+
 static PyObject *
 realize_c_type_or_func(builder_c_t *builder,
                         _cffi_opcode_t opcodes[], int index)
@@ -660,10 +654,17 @@
         return x;
     }
 
-    opcodes[index] = (_cffi_opcode_t)255;   /* recursion detection */
+    if (_realize_recursion_level >= 1000) {
+        PyErr_Format(PyExc_RuntimeError,
+            "type-building recursion too deep or infinite.  "
+            "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;
+    }
+    _realize_recursion_level++;
     x = realize_c_type_or_func_now(builder, op, opcodes, index);
-    if (opcodes[index] == (_cffi_opcode_t)255)
-        opcodes[index] = op;
+    _realize_recursion_level--;
 
     if (x != NULL && opcodes == builder->ctx.types && opcodes[index] != x) {
         assert((((uintptr_t)x) & 1) == 0);
diff --git a/testing/cffi1/test_re_python.py b/testing/cffi1/test_re_python.py
--- a/testing/cffi1/test_re_python.py
+++ b/testing/cffi1/test_re_python.py
@@ -75,6 +75,7 @@
     struct with_union { union { int a; char b; }; };
     union with_struct { struct { int a; char b; }; };
     struct NVGcolor { union { float rgba[4]; struct { float r,g,b,a; }; }; };
+    typedef struct selfref { struct selfref *next; } *selfref_ptr_t;
     """)
     ffi.set_source('re_python_pysrc', None)
     ffi.emit_python_code(str(tmpdir.join('re_python_pysrc.py')))
@@ -254,3 +255,8 @@
     assert ffi.offsetof("struct NVGcolor", "g") == FLOAT
     assert ffi.offsetof("struct NVGcolor", "b") == FLOAT * 2
     assert ffi.offsetof("struct NVGcolor", "a") == FLOAT * 3
+
+def test_selfref():
+    # based on issue #429
+    from re_python_pysrc import ffi
+    ffi.new("selfref_ptr_t")
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to