]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.9] bpo-11105: Do not crash when compiling recursive ASTs (GH-20594) (GH-26522)
authorBatuhan Taskaya <batuhan@python.org>
Thu, 3 Jun 2021 21:22:34 +0000 (00:22 +0300)
committerGitHub <noreply@github.com>
Thu, 3 Jun 2021 21:22:34 +0000 (22:22 +0100)
When compiling an AST object with a direct / indirect reference
cycles, on the conversion phase because of exceeding amount of
calls, a segfault was raised. This patch adds recursion guards to
places for preventing user inputs to not to crash AST but instead
raise a RecursionError..
(cherry picked from commit f3491242e41933aa9529add7102edb68b80a25e9)

Co-authored-by: Batuhan Taskaya <batuhan@python.org>
Lib/test/test_ast.py
Misc/NEWS.d/next/Core and Builtins/2020-06-02-13-21-14.bpo-11105.wceryW.rst [new file with mode: 0644]
Parser/asdl_c.py
Python/Python-ast.c

index 5f57ce8724482af4fcc0611805ded5bf3482e4e9..b229921f5c07c5eaeb52551d2a1bd979cdd280be 100644 (file)
@@ -1027,6 +1027,20 @@ Module(
         exec(code, ns)
         self.assertIn('sleep', ns)
 
+    def test_recursion_direct(self):
+        e = ast.UnaryOp(op=ast.Not(), lineno=0, col_offset=0)
+        e.operand = e
+        with self.assertRaises(RecursionError):
+            compile(ast.Expression(e), "<test>", "eval")
+
+    def test_recursion_indirect(self):
+        e = ast.UnaryOp(op=ast.Not(), lineno=0, col_offset=0)
+        f = ast.UnaryOp(op=ast.Not(), lineno=0, col_offset=0)
+        e.operand = f
+        f.operand = e
+        with self.assertRaises(RecursionError):
+            compile(ast.Expression(e), "<test>", "eval")
+
 
 class ASTValidatorTests(unittest.TestCase):
 
diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-06-02-13-21-14.bpo-11105.wceryW.rst b/Misc/NEWS.d/next/Core and Builtins/2020-06-02-13-21-14.bpo-11105.wceryW.rst
new file mode 100644 (file)
index 0000000..8891936
--- /dev/null
@@ -0,0 +1,3 @@
+When compiling :class:`ast.AST` objects with recursive references
+through :func:`compile`, the interpreter doesn't crash anymore instead
+it raises a :exc:`RecursionError`.
index 6f3154aeb6fc26f9a7fa342324cea58cabe888c8..4787050f92c30f506654f0c8f48699575ec6e22e 100755 (executable)
@@ -5,6 +5,7 @@ import os
 import sys
 
 from argparse import ArgumentParser
+from contextlib import contextmanager
 from pathlib import Path
 
 import asdl
@@ -394,6 +395,14 @@ class Obj2ModPrototypeVisitor(PickleVisitor):
 
 
 class Obj2ModVisitor(PickleVisitor):
+    @contextmanager
+    def recursive_call(self, node, level):
+        self.emit('if (Py_EnterRecursiveCall(" while traversing \'%s\' node")) {' % node, level, reflow=False)
+        self.emit('goto failed;', level + 1)
+        self.emit('}', level)
+        yield
+        self.emit('Py_LeaveRecursiveCall();', level)
+
     def funcHeader(self, name):
         ctype = get_c_type(name)
         self.emit("int", 0)
@@ -568,8 +577,9 @@ class Obj2ModVisitor(PickleVisitor):
             self.emit("%s val;" % ctype, depth+2)
             self.emit("PyObject *tmp2 = PyList_GET_ITEM(tmp, i);", depth+2)
             self.emit("Py_INCREF(tmp2);", depth+2)
-            self.emit("res = obj2ast_%s(state, tmp2, &val, arena);" %
-                      field.type, depth+2, reflow=False)
+            with self.recursive_call(name, depth+2):
+                self.emit("res = obj2ast_%s(state, tmp2, &val, arena);" %
+                          field.type, depth+2, reflow=False)
             self.emit("Py_DECREF(tmp2);", depth+2)
             self.emit("if (res != 0) goto failed;", depth+2)
             self.emit("if (len != PyList_GET_SIZE(tmp)) {", depth+2)
@@ -582,8 +592,9 @@ class Obj2ModVisitor(PickleVisitor):
             self.emit("asdl_seq_SET(%s, i, val);" % field.name, depth+2)
             self.emit("}", depth+1)
         else:
-            self.emit("res = obj2ast_%s(state, tmp, &%s, arena);" %
-                      (field.type, field.name), depth+1)
+            with self.recursive_call(name, depth+1):
+                self.emit("res = obj2ast_%s(state, tmp, &%s, arena);" %
+                          (field.type, field.name), depth+1)
             self.emit("if (res != 0) goto failed;", depth+1)
 
         self.emit("Py_CLEAR(tmp);", depth+1)
index 9e86f43178957d30d0ff45078791f11a3a9b055f..8b1c594a878bcc43ad7e125b82f0b1f9352d12f1 100644 (file)
@@ -4924,7 +4924,11 @@ obj2ast_mod(astmodulestate *state, PyObject* obj, mod_ty* out, PyArena* arena)
                 stmt_ty val;
                 PyObject *tmp2 = PyList_GET_ITEM(tmp, i);
                 Py_INCREF(tmp2);
+                if (Py_EnterRecursiveCall(" while traversing 'Module' node")) {
+                    goto failed;
+                }
                 res = obj2ast_stmt(state, tmp2, &val, arena);
+                Py_LeaveRecursiveCall();
                 Py_DECREF(tmp2);
                 if (res != 0) goto failed;
                 if (len != PyList_GET_SIZE(tmp)) {
@@ -4957,7 +4961,11 @@ obj2ast_mod(astmodulestate *state, PyObject* obj, mod_ty* out, PyArena* arena)
                 type_ignore_ty val;
                 PyObject *tmp2 = PyList_GET_ITEM(tmp, i);
                 Py_INCREF(tmp2);
+                if (Py_EnterRecursiveCall(" while traversing 'Module' node")) {
+                    goto failed;
+                }
                 res = obj2ast_type_ignore(state, tmp2, &val, arena);
+                Py_LeaveRecursiveCall();
                 Py_DECREF(tmp2);
                 if (res != 0) goto failed;
                 if (len != PyList_GET_SIZE(tmp)) {
@@ -5002,7 +5010,11 @@ obj2ast_mod(astmodulestate *state, PyObject* obj, mod_ty* out, PyArena* arena)
                 stmt_ty val;
                 PyObject *tmp2 = PyList_GET_ITEM(tmp, i);
                 Py_INCREF(tmp2);
+                if (Py_EnterRecursiveCall(" while traversing 'Interactive' node")) {
+                    goto failed;
+                }
                 res = obj2ast_stmt(state, tmp2, &val, arena);
+                Py_LeaveRecursiveCall();
                 Py_DECREF(tmp2);
                 if (res != 0) goto failed;
                 if (len != PyList_GET_SIZE(tmp)) {
@@ -5034,7 +5046,11 @@ obj2ast_mod(astmodulestate *state, PyObject* obj, mod_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'Expression' node")) {
+                goto failed;
+            }
             res = obj2ast_expr(state, tmp, &body, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -5073,7 +5089,11 @@ obj2ast_mod(astmodulestate *state, PyObject* obj, mod_ty* out, PyArena* arena)
                 expr_ty val;
                 PyObject *tmp2 = PyList_GET_ITEM(tmp, i);
                 Py_INCREF(tmp2);
+                if (Py_EnterRecursiveCall(" while traversing 'FunctionType' node")) {
+                    goto failed;
+                }
                 res = obj2ast_expr(state, tmp2, &val, arena);
+                Py_LeaveRecursiveCall();
                 Py_DECREF(tmp2);
                 if (res != 0) goto failed;
                 if (len != PyList_GET_SIZE(tmp)) {
@@ -5093,7 +5113,11 @@ obj2ast_mod(astmodulestate *state, PyObject* obj, mod_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'FunctionType' node")) {
+                goto failed;
+            }
             res = obj2ast_expr(state, tmp, &returns, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -5133,7 +5157,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
     }
     else {
         int res;
+        if (Py_EnterRecursiveCall(" while traversing 'stmt' node")) {
+            goto failed;
+        }
         res = obj2ast_int(state, tmp, &lineno, arena);
+        Py_LeaveRecursiveCall();
         if (res != 0) goto failed;
         Py_CLEAR(tmp);
     }
@@ -5146,7 +5174,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
     }
     else {
         int res;
+        if (Py_EnterRecursiveCall(" while traversing 'stmt' node")) {
+            goto failed;
+        }
         res = obj2ast_int(state, tmp, &col_offset, arena);
+        Py_LeaveRecursiveCall();
         if (res != 0) goto failed;
         Py_CLEAR(tmp);
     }
@@ -5159,7 +5191,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
     }
     else {
         int res;
+        if (Py_EnterRecursiveCall(" while traversing 'stmt' node")) {
+            goto failed;
+        }
         res = obj2ast_int(state, tmp, &end_lineno, arena);
+        Py_LeaveRecursiveCall();
         if (res != 0) goto failed;
         Py_CLEAR(tmp);
     }
@@ -5172,7 +5208,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
     }
     else {
         int res;
+        if (Py_EnterRecursiveCall(" while traversing 'stmt' node")) {
+            goto failed;
+        }
         res = obj2ast_int(state, tmp, &end_col_offset, arena);
+        Py_LeaveRecursiveCall();
         if (res != 0) goto failed;
         Py_CLEAR(tmp);
     }
@@ -5198,7 +5238,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'FunctionDef' node")) {
+                goto failed;
+            }
             res = obj2ast_identifier(state, tmp, &name, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -5211,7 +5255,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'FunctionDef' node")) {
+                goto failed;
+            }
             res = obj2ast_arguments(state, tmp, &args, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -5237,7 +5285,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
                 stmt_ty val;
                 PyObject *tmp2 = PyList_GET_ITEM(tmp, i);
                 Py_INCREF(tmp2);
+                if (Py_EnterRecursiveCall(" while traversing 'FunctionDef' node")) {
+                    goto failed;
+                }
                 res = obj2ast_stmt(state, tmp2, &val, arena);
+                Py_LeaveRecursiveCall();
                 Py_DECREF(tmp2);
                 if (res != 0) goto failed;
                 if (len != PyList_GET_SIZE(tmp)) {
@@ -5270,7 +5322,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
                 expr_ty val;
                 PyObject *tmp2 = PyList_GET_ITEM(tmp, i);
                 Py_INCREF(tmp2);
+                if (Py_EnterRecursiveCall(" while traversing 'FunctionDef' node")) {
+                    goto failed;
+                }
                 res = obj2ast_expr(state, tmp2, &val, arena);
+                Py_LeaveRecursiveCall();
                 Py_DECREF(tmp2);
                 if (res != 0) goto failed;
                 if (len != PyList_GET_SIZE(tmp)) {
@@ -5290,7 +5346,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'FunctionDef' node")) {
+                goto failed;
+            }
             res = obj2ast_expr(state, tmp, &returns, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -5303,7 +5363,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'FunctionDef' node")) {
+                goto failed;
+            }
             res = obj2ast_string(state, tmp, &type_comment, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -5335,7 +5399,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'AsyncFunctionDef' node")) {
+                goto failed;
+            }
             res = obj2ast_identifier(state, tmp, &name, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -5348,7 +5416,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'AsyncFunctionDef' node")) {
+                goto failed;
+            }
             res = obj2ast_arguments(state, tmp, &args, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -5374,7 +5446,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
                 stmt_ty val;
                 PyObject *tmp2 = PyList_GET_ITEM(tmp, i);
                 Py_INCREF(tmp2);
+                if (Py_EnterRecursiveCall(" while traversing 'AsyncFunctionDef' node")) {
+                    goto failed;
+                }
                 res = obj2ast_stmt(state, tmp2, &val, arena);
+                Py_LeaveRecursiveCall();
                 Py_DECREF(tmp2);
                 if (res != 0) goto failed;
                 if (len != PyList_GET_SIZE(tmp)) {
@@ -5407,7 +5483,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
                 expr_ty val;
                 PyObject *tmp2 = PyList_GET_ITEM(tmp, i);
                 Py_INCREF(tmp2);
+                if (Py_EnterRecursiveCall(" while traversing 'AsyncFunctionDef' node")) {
+                    goto failed;
+                }
                 res = obj2ast_expr(state, tmp2, &val, arena);
+                Py_LeaveRecursiveCall();
                 Py_DECREF(tmp2);
                 if (res != 0) goto failed;
                 if (len != PyList_GET_SIZE(tmp)) {
@@ -5427,7 +5507,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'AsyncFunctionDef' node")) {
+                goto failed;
+            }
             res = obj2ast_expr(state, tmp, &returns, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -5440,7 +5524,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'AsyncFunctionDef' node")) {
+                goto failed;
+            }
             res = obj2ast_string(state, tmp, &type_comment, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -5471,7 +5559,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'ClassDef' node")) {
+                goto failed;
+            }
             res = obj2ast_identifier(state, tmp, &name, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -5497,7 +5589,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
                 expr_ty val;
                 PyObject *tmp2 = PyList_GET_ITEM(tmp, i);
                 Py_INCREF(tmp2);
+                if (Py_EnterRecursiveCall(" while traversing 'ClassDef' node")) {
+                    goto failed;
+                }
                 res = obj2ast_expr(state, tmp2, &val, arena);
+                Py_LeaveRecursiveCall();
                 Py_DECREF(tmp2);
                 if (res != 0) goto failed;
                 if (len != PyList_GET_SIZE(tmp)) {
@@ -5530,7 +5626,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
                 keyword_ty val;
                 PyObject *tmp2 = PyList_GET_ITEM(tmp, i);
                 Py_INCREF(tmp2);
+                if (Py_EnterRecursiveCall(" while traversing 'ClassDef' node")) {
+                    goto failed;
+                }
                 res = obj2ast_keyword(state, tmp2, &val, arena);
+                Py_LeaveRecursiveCall();
                 Py_DECREF(tmp2);
                 if (res != 0) goto failed;
                 if (len != PyList_GET_SIZE(tmp)) {
@@ -5563,7 +5663,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
                 stmt_ty val;
                 PyObject *tmp2 = PyList_GET_ITEM(tmp, i);
                 Py_INCREF(tmp2);
+                if (Py_EnterRecursiveCall(" while traversing 'ClassDef' node")) {
+                    goto failed;
+                }
                 res = obj2ast_stmt(state, tmp2, &val, arena);
+                Py_LeaveRecursiveCall();
                 Py_DECREF(tmp2);
                 if (res != 0) goto failed;
                 if (len != PyList_GET_SIZE(tmp)) {
@@ -5596,7 +5700,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
                 expr_ty val;
                 PyObject *tmp2 = PyList_GET_ITEM(tmp, i);
                 Py_INCREF(tmp2);
+                if (Py_EnterRecursiveCall(" while traversing 'ClassDef' node")) {
+                    goto failed;
+                }
                 res = obj2ast_expr(state, tmp2, &val, arena);
+                Py_LeaveRecursiveCall();
                 Py_DECREF(tmp2);
                 if (res != 0) goto failed;
                 if (len != PyList_GET_SIZE(tmp)) {
@@ -5629,7 +5737,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'Return' node")) {
+                goto failed;
+            }
             res = obj2ast_expr(state, tmp, &value, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -5668,7 +5780,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
                 expr_ty val;
                 PyObject *tmp2 = PyList_GET_ITEM(tmp, i);
                 Py_INCREF(tmp2);
+                if (Py_EnterRecursiveCall(" while traversing 'Delete' node")) {
+                    goto failed;
+                }
                 res = obj2ast_expr(state, tmp2, &val, arena);
+                Py_LeaveRecursiveCall();
                 Py_DECREF(tmp2);
                 if (res != 0) goto failed;
                 if (len != PyList_GET_SIZE(tmp)) {
@@ -5716,7 +5832,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
                 expr_ty val;
                 PyObject *tmp2 = PyList_GET_ITEM(tmp, i);
                 Py_INCREF(tmp2);
+                if (Py_EnterRecursiveCall(" while traversing 'Assign' node")) {
+                    goto failed;
+                }
                 res = obj2ast_expr(state, tmp2, &val, arena);
+                Py_LeaveRecursiveCall();
                 Py_DECREF(tmp2);
                 if (res != 0) goto failed;
                 if (len != PyList_GET_SIZE(tmp)) {
@@ -5736,7 +5856,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'Assign' node")) {
+                goto failed;
+            }
             res = obj2ast_expr(state, tmp, &value, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -5749,7 +5873,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'Assign' node")) {
+                goto failed;
+            }
             res = obj2ast_string(state, tmp, &type_comment, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -5777,7 +5905,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'AugAssign' node")) {
+                goto failed;
+            }
             res = obj2ast_expr(state, tmp, &target, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -5790,7 +5922,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'AugAssign' node")) {
+                goto failed;
+            }
             res = obj2ast_operator(state, tmp, &op, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -5803,7 +5939,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'AugAssign' node")) {
+                goto failed;
+            }
             res = obj2ast_expr(state, tmp, &value, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -5832,7 +5972,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'AnnAssign' node")) {
+                goto failed;
+            }
             res = obj2ast_expr(state, tmp, &target, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -5845,7 +5989,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'AnnAssign' node")) {
+                goto failed;
+            }
             res = obj2ast_expr(state, tmp, &annotation, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -5858,7 +6006,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'AnnAssign' node")) {
+                goto failed;
+            }
             res = obj2ast_expr(state, tmp, &value, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -5871,7 +6023,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'AnnAssign' node")) {
+                goto failed;
+            }
             res = obj2ast_int(state, tmp, &simple, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -5901,7 +6057,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'For' node")) {
+                goto failed;
+            }
             res = obj2ast_expr(state, tmp, &target, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -5914,7 +6074,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'For' node")) {
+                goto failed;
+            }
             res = obj2ast_expr(state, tmp, &iter, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -5940,7 +6104,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
                 stmt_ty val;
                 PyObject *tmp2 = PyList_GET_ITEM(tmp, i);
                 Py_INCREF(tmp2);
+                if (Py_EnterRecursiveCall(" while traversing 'For' node")) {
+                    goto failed;
+                }
                 res = obj2ast_stmt(state, tmp2, &val, arena);
+                Py_LeaveRecursiveCall();
                 Py_DECREF(tmp2);
                 if (res != 0) goto failed;
                 if (len != PyList_GET_SIZE(tmp)) {
@@ -5973,7 +6141,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
                 stmt_ty val;
                 PyObject *tmp2 = PyList_GET_ITEM(tmp, i);
                 Py_INCREF(tmp2);
+                if (Py_EnterRecursiveCall(" while traversing 'For' node")) {
+                    goto failed;
+                }
                 res = obj2ast_stmt(state, tmp2, &val, arena);
+                Py_LeaveRecursiveCall();
                 Py_DECREF(tmp2);
                 if (res != 0) goto failed;
                 if (len != PyList_GET_SIZE(tmp)) {
@@ -5993,7 +6165,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'For' node")) {
+                goto failed;
+            }
             res = obj2ast_string(state, tmp, &type_comment, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -6023,7 +6199,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'AsyncFor' node")) {
+                goto failed;
+            }
             res = obj2ast_expr(state, tmp, &target, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -6036,7 +6216,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'AsyncFor' node")) {
+                goto failed;
+            }
             res = obj2ast_expr(state, tmp, &iter, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -6062,7 +6246,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
                 stmt_ty val;
                 PyObject *tmp2 = PyList_GET_ITEM(tmp, i);
                 Py_INCREF(tmp2);
+                if (Py_EnterRecursiveCall(" while traversing 'AsyncFor' node")) {
+                    goto failed;
+                }
                 res = obj2ast_stmt(state, tmp2, &val, arena);
+                Py_LeaveRecursiveCall();
                 Py_DECREF(tmp2);
                 if (res != 0) goto failed;
                 if (len != PyList_GET_SIZE(tmp)) {
@@ -6095,7 +6283,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
                 stmt_ty val;
                 PyObject *tmp2 = PyList_GET_ITEM(tmp, i);
                 Py_INCREF(tmp2);
+                if (Py_EnterRecursiveCall(" while traversing 'AsyncFor' node")) {
+                    goto failed;
+                }
                 res = obj2ast_stmt(state, tmp2, &val, arena);
+                Py_LeaveRecursiveCall();
                 Py_DECREF(tmp2);
                 if (res != 0) goto failed;
                 if (len != PyList_GET_SIZE(tmp)) {
@@ -6115,7 +6307,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'AsyncFor' node")) {
+                goto failed;
+            }
             res = obj2ast_string(state, tmp, &type_comment, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -6143,7 +6339,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'While' node")) {
+                goto failed;
+            }
             res = obj2ast_expr(state, tmp, &test, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -6169,7 +6369,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
                 stmt_ty val;
                 PyObject *tmp2 = PyList_GET_ITEM(tmp, i);
                 Py_INCREF(tmp2);
+                if (Py_EnterRecursiveCall(" while traversing 'While' node")) {
+                    goto failed;
+                }
                 res = obj2ast_stmt(state, tmp2, &val, arena);
+                Py_LeaveRecursiveCall();
                 Py_DECREF(tmp2);
                 if (res != 0) goto failed;
                 if (len != PyList_GET_SIZE(tmp)) {
@@ -6202,7 +6406,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
                 stmt_ty val;
                 PyObject *tmp2 = PyList_GET_ITEM(tmp, i);
                 Py_INCREF(tmp2);
+                if (Py_EnterRecursiveCall(" while traversing 'While' node")) {
+                    goto failed;
+                }
                 res = obj2ast_stmt(state, tmp2, &val, arena);
+                Py_LeaveRecursiveCall();
                 Py_DECREF(tmp2);
                 if (res != 0) goto failed;
                 if (len != PyList_GET_SIZE(tmp)) {
@@ -6237,7 +6445,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'If' node")) {
+                goto failed;
+            }
             res = obj2ast_expr(state, tmp, &test, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -6263,7 +6475,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
                 stmt_ty val;
                 PyObject *tmp2 = PyList_GET_ITEM(tmp, i);
                 Py_INCREF(tmp2);
+                if (Py_EnterRecursiveCall(" while traversing 'If' node")) {
+                    goto failed;
+                }
                 res = obj2ast_stmt(state, tmp2, &val, arena);
+                Py_LeaveRecursiveCall();
                 Py_DECREF(tmp2);
                 if (res != 0) goto failed;
                 if (len != PyList_GET_SIZE(tmp)) {
@@ -6296,7 +6512,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
                 stmt_ty val;
                 PyObject *tmp2 = PyList_GET_ITEM(tmp, i);
                 Py_INCREF(tmp2);
+                if (Py_EnterRecursiveCall(" while traversing 'If' node")) {
+                    goto failed;
+                }
                 res = obj2ast_stmt(state, tmp2, &val, arena);
+                Py_LeaveRecursiveCall();
                 Py_DECREF(tmp2);
                 if (res != 0) goto failed;
                 if (len != PyList_GET_SIZE(tmp)) {
@@ -6344,7 +6564,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
                 withitem_ty val;
                 PyObject *tmp2 = PyList_GET_ITEM(tmp, i);
                 Py_INCREF(tmp2);
+                if (Py_EnterRecursiveCall(" while traversing 'With' node")) {
+                    goto failed;
+                }
                 res = obj2ast_withitem(state, tmp2, &val, arena);
+                Py_LeaveRecursiveCall();
                 Py_DECREF(tmp2);
                 if (res != 0) goto failed;
                 if (len != PyList_GET_SIZE(tmp)) {
@@ -6377,7 +6601,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
                 stmt_ty val;
                 PyObject *tmp2 = PyList_GET_ITEM(tmp, i);
                 Py_INCREF(tmp2);
+                if (Py_EnterRecursiveCall(" while traversing 'With' node")) {
+                    goto failed;
+                }
                 res = obj2ast_stmt(state, tmp2, &val, arena);
+                Py_LeaveRecursiveCall();
                 Py_DECREF(tmp2);
                 if (res != 0) goto failed;
                 if (len != PyList_GET_SIZE(tmp)) {
@@ -6397,7 +6625,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'With' node")) {
+                goto failed;
+            }
             res = obj2ast_string(state, tmp, &type_comment, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -6438,7 +6670,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
                 withitem_ty val;
                 PyObject *tmp2 = PyList_GET_ITEM(tmp, i);
                 Py_INCREF(tmp2);
+                if (Py_EnterRecursiveCall(" while traversing 'AsyncWith' node")) {
+                    goto failed;
+                }
                 res = obj2ast_withitem(state, tmp2, &val, arena);
+                Py_LeaveRecursiveCall();
                 Py_DECREF(tmp2);
                 if (res != 0) goto failed;
                 if (len != PyList_GET_SIZE(tmp)) {
@@ -6471,7 +6707,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
                 stmt_ty val;
                 PyObject *tmp2 = PyList_GET_ITEM(tmp, i);
                 Py_INCREF(tmp2);
+                if (Py_EnterRecursiveCall(" while traversing 'AsyncWith' node")) {
+                    goto failed;
+                }
                 res = obj2ast_stmt(state, tmp2, &val, arena);
+                Py_LeaveRecursiveCall();
                 Py_DECREF(tmp2);
                 if (res != 0) goto failed;
                 if (len != PyList_GET_SIZE(tmp)) {
@@ -6491,7 +6731,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'AsyncWith' node")) {
+                goto failed;
+            }
             res = obj2ast_string(state, tmp, &type_comment, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -6518,7 +6762,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'Raise' node")) {
+                goto failed;
+            }
             res = obj2ast_expr(state, tmp, &exc, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -6531,7 +6779,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'Raise' node")) {
+                goto failed;
+            }
             res = obj2ast_expr(state, tmp, &cause, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -6573,7 +6825,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
                 stmt_ty val;
                 PyObject *tmp2 = PyList_GET_ITEM(tmp, i);
                 Py_INCREF(tmp2);
+                if (Py_EnterRecursiveCall(" while traversing 'Try' node")) {
+                    goto failed;
+                }
                 res = obj2ast_stmt(state, tmp2, &val, arena);
+                Py_LeaveRecursiveCall();
                 Py_DECREF(tmp2);
                 if (res != 0) goto failed;
                 if (len != PyList_GET_SIZE(tmp)) {
@@ -6606,7 +6862,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
                 excepthandler_ty val;
                 PyObject *tmp2 = PyList_GET_ITEM(tmp, i);
                 Py_INCREF(tmp2);
+                if (Py_EnterRecursiveCall(" while traversing 'Try' node")) {
+                    goto failed;
+                }
                 res = obj2ast_excepthandler(state, tmp2, &val, arena);
+                Py_LeaveRecursiveCall();
                 Py_DECREF(tmp2);
                 if (res != 0) goto failed;
                 if (len != PyList_GET_SIZE(tmp)) {
@@ -6639,7 +6899,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
                 stmt_ty val;
                 PyObject *tmp2 = PyList_GET_ITEM(tmp, i);
                 Py_INCREF(tmp2);
+                if (Py_EnterRecursiveCall(" while traversing 'Try' node")) {
+                    goto failed;
+                }
                 res = obj2ast_stmt(state, tmp2, &val, arena);
+                Py_LeaveRecursiveCall();
                 Py_DECREF(tmp2);
                 if (res != 0) goto failed;
                 if (len != PyList_GET_SIZE(tmp)) {
@@ -6672,7 +6936,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
                 stmt_ty val;
                 PyObject *tmp2 = PyList_GET_ITEM(tmp, i);
                 Py_INCREF(tmp2);
+                if (Py_EnterRecursiveCall(" while traversing 'Try' node")) {
+                    goto failed;
+                }
                 res = obj2ast_stmt(state, tmp2, &val, arena);
+                Py_LeaveRecursiveCall();
                 Py_DECREF(tmp2);
                 if (res != 0) goto failed;
                 if (len != PyList_GET_SIZE(tmp)) {
@@ -6706,7 +6974,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'Assert' node")) {
+                goto failed;
+            }
             res = obj2ast_expr(state, tmp, &test, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -6719,7 +6991,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'Assert' node")) {
+                goto failed;
+            }
             res = obj2ast_expr(state, tmp, &msg, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -6758,7 +7034,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
                 alias_ty val;
                 PyObject *tmp2 = PyList_GET_ITEM(tmp, i);
                 Py_INCREF(tmp2);
+                if (Py_EnterRecursiveCall(" while traversing 'Import' node")) {
+                    goto failed;
+                }
                 res = obj2ast_alias(state, tmp2, &val, arena);
+                Py_LeaveRecursiveCall();
                 Py_DECREF(tmp2);
                 if (res != 0) goto failed;
                 if (len != PyList_GET_SIZE(tmp)) {
@@ -6793,7 +7073,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'ImportFrom' node")) {
+                goto failed;
+            }
             res = obj2ast_identifier(state, tmp, &module, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -6819,7 +7103,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
                 alias_ty val;
                 PyObject *tmp2 = PyList_GET_ITEM(tmp, i);
                 Py_INCREF(tmp2);
+                if (Py_EnterRecursiveCall(" while traversing 'ImportFrom' node")) {
+                    goto failed;
+                }
                 res = obj2ast_alias(state, tmp2, &val, arena);
+                Py_LeaveRecursiveCall();
                 Py_DECREF(tmp2);
                 if (res != 0) goto failed;
                 if (len != PyList_GET_SIZE(tmp)) {
@@ -6839,7 +7127,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'ImportFrom' node")) {
+                goto failed;
+            }
             res = obj2ast_int(state, tmp, &level, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -6878,7 +7170,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
                 identifier val;
                 PyObject *tmp2 = PyList_GET_ITEM(tmp, i);
                 Py_INCREF(tmp2);
+                if (Py_EnterRecursiveCall(" while traversing 'Global' node")) {
+                    goto failed;
+                }
                 res = obj2ast_identifier(state, tmp2, &val, arena);
+                Py_LeaveRecursiveCall();
                 Py_DECREF(tmp2);
                 if (res != 0) goto failed;
                 if (len != PyList_GET_SIZE(tmp)) {
@@ -6924,7 +7220,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
                 identifier val;
                 PyObject *tmp2 = PyList_GET_ITEM(tmp, i);
                 Py_INCREF(tmp2);
+                if (Py_EnterRecursiveCall(" while traversing 'Nonlocal' node")) {
+                    goto failed;
+                }
                 res = obj2ast_identifier(state, tmp2, &val, arena);
+                Py_LeaveRecursiveCall();
                 Py_DECREF(tmp2);
                 if (res != 0) goto failed;
                 if (len != PyList_GET_SIZE(tmp)) {
@@ -6957,7 +7257,11 @@ obj2ast_stmt(astmodulestate *state, PyObject* obj, stmt_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'Expr' node")) {
+                goto failed;
+            }
             res = obj2ast_expr(state, tmp, &value, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -7031,7 +7335,11 @@ obj2ast_expr(astmodulestate *state, PyObject* obj, expr_ty* out, PyArena* arena)
     }
     else {
         int res;
+        if (Py_EnterRecursiveCall(" while traversing 'expr' node")) {
+            goto failed;
+        }
         res = obj2ast_int(state, tmp, &lineno, arena);
+        Py_LeaveRecursiveCall();
         if (res != 0) goto failed;
         Py_CLEAR(tmp);
     }
@@ -7044,7 +7352,11 @@ obj2ast_expr(astmodulestate *state, PyObject* obj, expr_ty* out, PyArena* arena)
     }
     else {
         int res;
+        if (Py_EnterRecursiveCall(" while traversing 'expr' node")) {
+            goto failed;
+        }
         res = obj2ast_int(state, tmp, &col_offset, arena);
+        Py_LeaveRecursiveCall();
         if (res != 0) goto failed;
         Py_CLEAR(tmp);
     }
@@ -7057,7 +7369,11 @@ obj2ast_expr(astmodulestate *state, PyObject* obj, expr_ty* out, PyArena* arena)
     }
     else {
         int res;
+        if (Py_EnterRecursiveCall(" while traversing 'expr' node")) {
+            goto failed;
+        }
         res = obj2ast_int(state, tmp, &end_lineno, arena);
+        Py_LeaveRecursiveCall();
         if (res != 0) goto failed;
         Py_CLEAR(tmp);
     }
@@ -7070,7 +7386,11 @@ obj2ast_expr(astmodulestate *state, PyObject* obj, expr_ty* out, PyArena* arena)
     }
     else {
         int res;
+        if (Py_EnterRecursiveCall(" while traversing 'expr' node")) {
+            goto failed;
+        }
         res = obj2ast_int(state, tmp, &end_col_offset, arena);
+        Py_LeaveRecursiveCall();
         if (res != 0) goto failed;
         Py_CLEAR(tmp);
     }
@@ -7092,7 +7412,11 @@ obj2ast_expr(astmodulestate *state, PyObject* obj, expr_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'BoolOp' node")) {
+                goto failed;
+            }
             res = obj2ast_boolop(state, tmp, &op, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -7118,7 +7442,11 @@ obj2ast_expr(astmodulestate *state, PyObject* obj, expr_ty* out, PyArena* arena)
                 expr_ty val;
                 PyObject *tmp2 = PyList_GET_ITEM(tmp, i);
                 Py_INCREF(tmp2);
+                if (Py_EnterRecursiveCall(" while traversing 'BoolOp' node")) {
+                    goto failed;
+                }
                 res = obj2ast_expr(state, tmp2, &val, arena);
+                Py_LeaveRecursiveCall();
                 Py_DECREF(tmp2);
                 if (res != 0) goto failed;
                 if (len != PyList_GET_SIZE(tmp)) {
@@ -7152,7 +7480,11 @@ obj2ast_expr(astmodulestate *state, PyObject* obj, expr_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'NamedExpr' node")) {
+                goto failed;
+            }
             res = obj2ast_expr(state, tmp, &target, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -7165,7 +7497,11 @@ obj2ast_expr(astmodulestate *state, PyObject* obj, expr_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'NamedExpr' node")) {
+                goto failed;
+            }
             res = obj2ast_expr(state, tmp, &value, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -7193,7 +7529,11 @@ obj2ast_expr(astmodulestate *state, PyObject* obj, expr_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'BinOp' node")) {
+                goto failed;
+            }
             res = obj2ast_expr(state, tmp, &left, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -7206,7 +7546,11 @@ obj2ast_expr(astmodulestate *state, PyObject* obj, expr_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'BinOp' node")) {
+                goto failed;
+            }
             res = obj2ast_operator(state, tmp, &op, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -7219,7 +7563,11 @@ obj2ast_expr(astmodulestate *state, PyObject* obj, expr_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'BinOp' node")) {
+                goto failed;
+            }
             res = obj2ast_expr(state, tmp, &right, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -7246,7 +7594,11 @@ obj2ast_expr(astmodulestate *state, PyObject* obj, expr_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'UnaryOp' node")) {
+                goto failed;
+            }
             res = obj2ast_unaryop(state, tmp, &op, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -7259,7 +7611,11 @@ obj2ast_expr(astmodulestate *state, PyObject* obj, expr_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'UnaryOp' node")) {
+                goto failed;
+            }
             res = obj2ast_expr(state, tmp, &operand, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -7286,7 +7642,11 @@ obj2ast_expr(astmodulestate *state, PyObject* obj, expr_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'Lambda' node")) {
+                goto failed;
+            }
             res = obj2ast_arguments(state, tmp, &args, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -7299,7 +7659,11 @@ obj2ast_expr(astmodulestate *state, PyObject* obj, expr_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'Lambda' node")) {
+                goto failed;
+            }
             res = obj2ast_expr(state, tmp, &body, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -7327,7 +7691,11 @@ obj2ast_expr(astmodulestate *state, PyObject* obj, expr_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'IfExp' node")) {
+                goto failed;
+            }
             res = obj2ast_expr(state, tmp, &test, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -7340,7 +7708,11 @@ obj2ast_expr(astmodulestate *state, PyObject* obj, expr_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'IfExp' node")) {
+                goto failed;
+            }
             res = obj2ast_expr(state, tmp, &body, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -7353,7 +7725,11 @@ obj2ast_expr(astmodulestate *state, PyObject* obj, expr_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'IfExp' node")) {
+                goto failed;
+            }
             res = obj2ast_expr(state, tmp, &orelse, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -7393,7 +7769,11 @@ obj2ast_expr(astmodulestate *state, PyObject* obj, expr_ty* out, PyArena* arena)
                 expr_ty val;
                 PyObject *tmp2 = PyList_GET_ITEM(tmp, i);
                 Py_INCREF(tmp2);
+                if (Py_EnterRecursiveCall(" while traversing 'Dict' node")) {
+                    goto failed;
+                }
                 res = obj2ast_expr(state, tmp2, &val, arena);
+                Py_LeaveRecursiveCall();
                 Py_DECREF(tmp2);
                 if (res != 0) goto failed;
                 if (len != PyList_GET_SIZE(tmp)) {
@@ -7426,7 +7806,11 @@ obj2ast_expr(astmodulestate *state, PyObject* obj, expr_ty* out, PyArena* arena)
                 expr_ty val;
                 PyObject *tmp2 = PyList_GET_ITEM(tmp, i);
                 Py_INCREF(tmp2);
+                if (Py_EnterRecursiveCall(" while traversing 'Dict' node")) {
+                    goto failed;
+                }
                 res = obj2ast_expr(state, tmp2, &val, arena);
+                Py_LeaveRecursiveCall();
                 Py_DECREF(tmp2);
                 if (res != 0) goto failed;
                 if (len != PyList_GET_SIZE(tmp)) {
@@ -7472,7 +7856,11 @@ obj2ast_expr(astmodulestate *state, PyObject* obj, expr_ty* out, PyArena* arena)
                 expr_ty val;
                 PyObject *tmp2 = PyList_GET_ITEM(tmp, i);
                 Py_INCREF(tmp2);
+                if (Py_EnterRecursiveCall(" while traversing 'Set' node")) {
+                    goto failed;
+                }
                 res = obj2ast_expr(state, tmp2, &val, arena);
+                Py_LeaveRecursiveCall();
                 Py_DECREF(tmp2);
                 if (res != 0) goto failed;
                 if (len != PyList_GET_SIZE(tmp)) {
@@ -7505,7 +7893,11 @@ obj2ast_expr(astmodulestate *state, PyObject* obj, expr_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'ListComp' node")) {
+                goto failed;
+            }
             res = obj2ast_expr(state, tmp, &elt, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -7531,7 +7923,11 @@ obj2ast_expr(astmodulestate *state, PyObject* obj, expr_ty* out, PyArena* arena)
                 comprehension_ty val;
                 PyObject *tmp2 = PyList_GET_ITEM(tmp, i);
                 Py_INCREF(tmp2);
+                if (Py_EnterRecursiveCall(" while traversing 'ListComp' node")) {
+                    goto failed;
+                }
                 res = obj2ast_comprehension(state, tmp2, &val, arena);
+                Py_LeaveRecursiveCall();
                 Py_DECREF(tmp2);
                 if (res != 0) goto failed;
                 if (len != PyList_GET_SIZE(tmp)) {
@@ -7565,7 +7961,11 @@ obj2ast_expr(astmodulestate *state, PyObject* obj, expr_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'SetComp' node")) {
+                goto failed;
+            }
             res = obj2ast_expr(state, tmp, &elt, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -7591,7 +7991,11 @@ obj2ast_expr(astmodulestate *state, PyObject* obj, expr_ty* out, PyArena* arena)
                 comprehension_ty val;
                 PyObject *tmp2 = PyList_GET_ITEM(tmp, i);
                 Py_INCREF(tmp2);
+                if (Py_EnterRecursiveCall(" while traversing 'SetComp' node")) {
+                    goto failed;
+                }
                 res = obj2ast_comprehension(state, tmp2, &val, arena);
+                Py_LeaveRecursiveCall();
                 Py_DECREF(tmp2);
                 if (res != 0) goto failed;
                 if (len != PyList_GET_SIZE(tmp)) {
@@ -7626,7 +8030,11 @@ obj2ast_expr(astmodulestate *state, PyObject* obj, expr_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'DictComp' node")) {
+                goto failed;
+            }
             res = obj2ast_expr(state, tmp, &key, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -7639,7 +8047,11 @@ obj2ast_expr(astmodulestate *state, PyObject* obj, expr_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'DictComp' node")) {
+                goto failed;
+            }
             res = obj2ast_expr(state, tmp, &value, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -7665,7 +8077,11 @@ obj2ast_expr(astmodulestate *state, PyObject* obj, expr_ty* out, PyArena* arena)
                 comprehension_ty val;
                 PyObject *tmp2 = PyList_GET_ITEM(tmp, i);
                 Py_INCREF(tmp2);
+                if (Py_EnterRecursiveCall(" while traversing 'DictComp' node")) {
+                    goto failed;
+                }
                 res = obj2ast_comprehension(state, tmp2, &val, arena);
+                Py_LeaveRecursiveCall();
                 Py_DECREF(tmp2);
                 if (res != 0) goto failed;
                 if (len != PyList_GET_SIZE(tmp)) {
@@ -7699,7 +8115,11 @@ obj2ast_expr(astmodulestate *state, PyObject* obj, expr_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'GeneratorExp' node")) {
+                goto failed;
+            }
             res = obj2ast_expr(state, tmp, &elt, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -7725,7 +8145,11 @@ obj2ast_expr(astmodulestate *state, PyObject* obj, expr_ty* out, PyArena* arena)
                 comprehension_ty val;
                 PyObject *tmp2 = PyList_GET_ITEM(tmp, i);
                 Py_INCREF(tmp2);
+                if (Py_EnterRecursiveCall(" while traversing 'GeneratorExp' node")) {
+                    goto failed;
+                }
                 res = obj2ast_comprehension(state, tmp2, &val, arena);
+                Py_LeaveRecursiveCall();
                 Py_DECREF(tmp2);
                 if (res != 0) goto failed;
                 if (len != PyList_GET_SIZE(tmp)) {
@@ -7758,7 +8182,11 @@ obj2ast_expr(astmodulestate *state, PyObject* obj, expr_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'Await' node")) {
+                goto failed;
+            }
             res = obj2ast_expr(state, tmp, &value, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -7784,7 +8212,11 @@ obj2ast_expr(astmodulestate *state, PyObject* obj, expr_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'Yield' node")) {
+                goto failed;
+            }
             res = obj2ast_expr(state, tmp, &value, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -7810,7 +8242,11 @@ obj2ast_expr(astmodulestate *state, PyObject* obj, expr_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'YieldFrom' node")) {
+                goto failed;
+            }
             res = obj2ast_expr(state, tmp, &value, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -7838,7 +8274,11 @@ obj2ast_expr(astmodulestate *state, PyObject* obj, expr_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'Compare' node")) {
+                goto failed;
+            }
             res = obj2ast_expr(state, tmp, &left, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -7864,7 +8304,11 @@ obj2ast_expr(astmodulestate *state, PyObject* obj, expr_ty* out, PyArena* arena)
                 cmpop_ty val;
                 PyObject *tmp2 = PyList_GET_ITEM(tmp, i);
                 Py_INCREF(tmp2);
+                if (Py_EnterRecursiveCall(" while traversing 'Compare' node")) {
+                    goto failed;
+                }
                 res = obj2ast_cmpop(state, tmp2, &val, arena);
+                Py_LeaveRecursiveCall();
                 Py_DECREF(tmp2);
                 if (res != 0) goto failed;
                 if (len != PyList_GET_SIZE(tmp)) {
@@ -7897,7 +8341,11 @@ obj2ast_expr(astmodulestate *state, PyObject* obj, expr_ty* out, PyArena* arena)
                 expr_ty val;
                 PyObject *tmp2 = PyList_GET_ITEM(tmp, i);
                 Py_INCREF(tmp2);
+                if (Py_EnterRecursiveCall(" while traversing 'Compare' node")) {
+                    goto failed;
+                }
                 res = obj2ast_expr(state, tmp2, &val, arena);
+                Py_LeaveRecursiveCall();
                 Py_DECREF(tmp2);
                 if (res != 0) goto failed;
                 if (len != PyList_GET_SIZE(tmp)) {
@@ -7932,7 +8380,11 @@ obj2ast_expr(astmodulestate *state, PyObject* obj, expr_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'Call' node")) {
+                goto failed;
+            }
             res = obj2ast_expr(state, tmp, &func, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -7958,7 +8410,11 @@ obj2ast_expr(astmodulestate *state, PyObject* obj, expr_ty* out, PyArena* arena)
                 expr_ty val;
                 PyObject *tmp2 = PyList_GET_ITEM(tmp, i);
                 Py_INCREF(tmp2);
+                if (Py_EnterRecursiveCall(" while traversing 'Call' node")) {
+                    goto failed;
+                }
                 res = obj2ast_expr(state, tmp2, &val, arena);
+                Py_LeaveRecursiveCall();
                 Py_DECREF(tmp2);
                 if (res != 0) goto failed;
                 if (len != PyList_GET_SIZE(tmp)) {
@@ -7991,7 +8447,11 @@ obj2ast_expr(astmodulestate *state, PyObject* obj, expr_ty* out, PyArena* arena)
                 keyword_ty val;
                 PyObject *tmp2 = PyList_GET_ITEM(tmp, i);
                 Py_INCREF(tmp2);
+                if (Py_EnterRecursiveCall(" while traversing 'Call' node")) {
+                    goto failed;
+                }
                 res = obj2ast_keyword(state, tmp2, &val, arena);
+                Py_LeaveRecursiveCall();
                 Py_DECREF(tmp2);
                 if (res != 0) goto failed;
                 if (len != PyList_GET_SIZE(tmp)) {
@@ -8026,7 +8486,11 @@ obj2ast_expr(astmodulestate *state, PyObject* obj, expr_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'FormattedValue' node")) {
+                goto failed;
+            }
             res = obj2ast_expr(state, tmp, &value, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -8039,7 +8503,11 @@ obj2ast_expr(astmodulestate *state, PyObject* obj, expr_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'FormattedValue' node")) {
+                goto failed;
+            }
             res = obj2ast_int(state, tmp, &conversion, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -8052,7 +8520,11 @@ obj2ast_expr(astmodulestate *state, PyObject* obj, expr_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'FormattedValue' node")) {
+                goto failed;
+            }
             res = obj2ast_expr(state, tmp, &format_spec, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -8091,7 +8563,11 @@ obj2ast_expr(astmodulestate *state, PyObject* obj, expr_ty* out, PyArena* arena)
                 expr_ty val;
                 PyObject *tmp2 = PyList_GET_ITEM(tmp, i);
                 Py_INCREF(tmp2);
+                if (Py_EnterRecursiveCall(" while traversing 'JoinedStr' node")) {
+                    goto failed;
+                }
                 res = obj2ast_expr(state, tmp2, &val, arena);
+                Py_LeaveRecursiveCall();
                 Py_DECREF(tmp2);
                 if (res != 0) goto failed;
                 if (len != PyList_GET_SIZE(tmp)) {
@@ -8125,7 +8601,11 @@ obj2ast_expr(astmodulestate *state, PyObject* obj, expr_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'Constant' node")) {
+                goto failed;
+            }
             res = obj2ast_constant(state, tmp, &value, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -8138,7 +8618,11 @@ obj2ast_expr(astmodulestate *state, PyObject* obj, expr_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'Constant' node")) {
+                goto failed;
+            }
             res = obj2ast_string(state, tmp, &kind, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -8166,7 +8650,11 @@ obj2ast_expr(astmodulestate *state, PyObject* obj, expr_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'Attribute' node")) {
+                goto failed;
+            }
             res = obj2ast_expr(state, tmp, &value, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -8179,7 +8667,11 @@ obj2ast_expr(astmodulestate *state, PyObject* obj, expr_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'Attribute' node")) {
+                goto failed;
+            }
             res = obj2ast_identifier(state, tmp, &attr, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -8192,7 +8684,11 @@ obj2ast_expr(astmodulestate *state, PyObject* obj, expr_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'Attribute' node")) {
+                goto failed;
+            }
             res = obj2ast_expr_context(state, tmp, &ctx, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -8220,7 +8716,11 @@ obj2ast_expr(astmodulestate *state, PyObject* obj, expr_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'Subscript' node")) {
+                goto failed;
+            }
             res = obj2ast_expr(state, tmp, &value, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -8233,7 +8733,11 @@ obj2ast_expr(astmodulestate *state, PyObject* obj, expr_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'Subscript' node")) {
+                goto failed;
+            }
             res = obj2ast_expr(state, tmp, &slice, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -8246,7 +8750,11 @@ obj2ast_expr(astmodulestate *state, PyObject* obj, expr_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'Subscript' node")) {
+                goto failed;
+            }
             res = obj2ast_expr_context(state, tmp, &ctx, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -8273,7 +8781,11 @@ obj2ast_expr(astmodulestate *state, PyObject* obj, expr_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'Starred' node")) {
+                goto failed;
+            }
             res = obj2ast_expr(state, tmp, &value, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -8286,7 +8798,11 @@ obj2ast_expr(astmodulestate *state, PyObject* obj, expr_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'Starred' node")) {
+                goto failed;
+            }
             res = obj2ast_expr_context(state, tmp, &ctx, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -8313,7 +8829,11 @@ obj2ast_expr(astmodulestate *state, PyObject* obj, expr_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'Name' node")) {
+                goto failed;
+            }
             res = obj2ast_identifier(state, tmp, &id, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -8326,7 +8846,11 @@ obj2ast_expr(astmodulestate *state, PyObject* obj, expr_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'Name' node")) {
+                goto failed;
+            }
             res = obj2ast_expr_context(state, tmp, &ctx, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -8366,7 +8890,11 @@ obj2ast_expr(astmodulestate *state, PyObject* obj, expr_ty* out, PyArena* arena)
                 expr_ty val;
                 PyObject *tmp2 = PyList_GET_ITEM(tmp, i);
                 Py_INCREF(tmp2);
+                if (Py_EnterRecursiveCall(" while traversing 'List' node")) {
+                    goto failed;
+                }
                 res = obj2ast_expr(state, tmp2, &val, arena);
+                Py_LeaveRecursiveCall();
                 Py_DECREF(tmp2);
                 if (res != 0) goto failed;
                 if (len != PyList_GET_SIZE(tmp)) {
@@ -8386,7 +8914,11 @@ obj2ast_expr(astmodulestate *state, PyObject* obj, expr_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'List' node")) {
+                goto failed;
+            }
             res = obj2ast_expr_context(state, tmp, &ctx, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -8426,7 +8958,11 @@ obj2ast_expr(astmodulestate *state, PyObject* obj, expr_ty* out, PyArena* arena)
                 expr_ty val;
                 PyObject *tmp2 = PyList_GET_ITEM(tmp, i);
                 Py_INCREF(tmp2);
+                if (Py_EnterRecursiveCall(" while traversing 'Tuple' node")) {
+                    goto failed;
+                }
                 res = obj2ast_expr(state, tmp2, &val, arena);
+                Py_LeaveRecursiveCall();
                 Py_DECREF(tmp2);
                 if (res != 0) goto failed;
                 if (len != PyList_GET_SIZE(tmp)) {
@@ -8446,7 +8982,11 @@ obj2ast_expr(astmodulestate *state, PyObject* obj, expr_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'Tuple' node")) {
+                goto failed;
+            }
             res = obj2ast_expr_context(state, tmp, &ctx, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -8474,7 +9014,11 @@ obj2ast_expr(astmodulestate *state, PyObject* obj, expr_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'Slice' node")) {
+                goto failed;
+            }
             res = obj2ast_expr(state, tmp, &lower, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -8487,7 +9031,11 @@ obj2ast_expr(astmodulestate *state, PyObject* obj, expr_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'Slice' node")) {
+                goto failed;
+            }
             res = obj2ast_expr(state, tmp, &upper, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -8500,7 +9048,11 @@ obj2ast_expr(astmodulestate *state, PyObject* obj, expr_ty* out, PyArena* arena)
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'Slice' node")) {
+                goto failed;
+            }
             res = obj2ast_expr(state, tmp, &step, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -8846,7 +9398,11 @@ obj2ast_comprehension(astmodulestate *state, PyObject* obj, comprehension_ty*
     }
     else {
         int res;
+        if (Py_EnterRecursiveCall(" while traversing 'comprehension' node")) {
+            goto failed;
+        }
         res = obj2ast_expr(state, tmp, &target, arena);
+        Py_LeaveRecursiveCall();
         if (res != 0) goto failed;
         Py_CLEAR(tmp);
     }
@@ -8859,7 +9415,11 @@ obj2ast_comprehension(astmodulestate *state, PyObject* obj, comprehension_ty*
     }
     else {
         int res;
+        if (Py_EnterRecursiveCall(" while traversing 'comprehension' node")) {
+            goto failed;
+        }
         res = obj2ast_expr(state, tmp, &iter, arena);
+        Py_LeaveRecursiveCall();
         if (res != 0) goto failed;
         Py_CLEAR(tmp);
     }
@@ -8885,7 +9445,11 @@ obj2ast_comprehension(astmodulestate *state, PyObject* obj, comprehension_ty*
             expr_ty val;
             PyObject *tmp2 = PyList_GET_ITEM(tmp, i);
             Py_INCREF(tmp2);
+            if (Py_EnterRecursiveCall(" while traversing 'comprehension' node")) {
+                goto failed;
+            }
             res = obj2ast_expr(state, tmp2, &val, arena);
+            Py_LeaveRecursiveCall();
             Py_DECREF(tmp2);
             if (res != 0) goto failed;
             if (len != PyList_GET_SIZE(tmp)) {
@@ -8905,7 +9469,11 @@ obj2ast_comprehension(astmodulestate *state, PyObject* obj, comprehension_ty*
     }
     else {
         int res;
+        if (Py_EnterRecursiveCall(" while traversing 'comprehension' node")) {
+            goto failed;
+        }
         res = obj2ast_int(state, tmp, &is_async, arena);
+        Py_LeaveRecursiveCall();
         if (res != 0) goto failed;
         Py_CLEAR(tmp);
     }
@@ -8942,7 +9510,11 @@ obj2ast_excepthandler(astmodulestate *state, PyObject* obj, excepthandler_ty*
     }
     else {
         int res;
+        if (Py_EnterRecursiveCall(" while traversing 'excepthandler' node")) {
+            goto failed;
+        }
         res = obj2ast_int(state, tmp, &lineno, arena);
+        Py_LeaveRecursiveCall();
         if (res != 0) goto failed;
         Py_CLEAR(tmp);
     }
@@ -8955,7 +9527,11 @@ obj2ast_excepthandler(astmodulestate *state, PyObject* obj, excepthandler_ty*
     }
     else {
         int res;
+        if (Py_EnterRecursiveCall(" while traversing 'excepthandler' node")) {
+            goto failed;
+        }
         res = obj2ast_int(state, tmp, &col_offset, arena);
+        Py_LeaveRecursiveCall();
         if (res != 0) goto failed;
         Py_CLEAR(tmp);
     }
@@ -8968,7 +9544,11 @@ obj2ast_excepthandler(astmodulestate *state, PyObject* obj, excepthandler_ty*
     }
     else {
         int res;
+        if (Py_EnterRecursiveCall(" while traversing 'excepthandler' node")) {
+            goto failed;
+        }
         res = obj2ast_int(state, tmp, &end_lineno, arena);
+        Py_LeaveRecursiveCall();
         if (res != 0) goto failed;
         Py_CLEAR(tmp);
     }
@@ -8981,7 +9561,11 @@ obj2ast_excepthandler(astmodulestate *state, PyObject* obj, excepthandler_ty*
     }
     else {
         int res;
+        if (Py_EnterRecursiveCall(" while traversing 'excepthandler' node")) {
+            goto failed;
+        }
         res = obj2ast_int(state, tmp, &end_col_offset, arena);
+        Py_LeaveRecursiveCall();
         if (res != 0) goto failed;
         Py_CLEAR(tmp);
     }
@@ -9004,7 +9588,11 @@ obj2ast_excepthandler(astmodulestate *state, PyObject* obj, excepthandler_ty*
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'ExceptHandler' node")) {
+                goto failed;
+            }
             res = obj2ast_expr(state, tmp, &type, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -9017,7 +9605,11 @@ obj2ast_excepthandler(astmodulestate *state, PyObject* obj, excepthandler_ty*
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'ExceptHandler' node")) {
+                goto failed;
+            }
             res = obj2ast_identifier(state, tmp, &name, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -9043,7 +9635,11 @@ obj2ast_excepthandler(astmodulestate *state, PyObject* obj, excepthandler_ty*
                 stmt_ty val;
                 PyObject *tmp2 = PyList_GET_ITEM(tmp, i);
                 Py_INCREF(tmp2);
+                if (Py_EnterRecursiveCall(" while traversing 'ExceptHandler' node")) {
+                    goto failed;
+                }
                 res = obj2ast_stmt(state, tmp2, &val, arena);
+                Py_LeaveRecursiveCall();
                 Py_DECREF(tmp2);
                 if (res != 0) goto failed;
                 if (len != PyList_GET_SIZE(tmp)) {
@@ -9101,7 +9697,11 @@ obj2ast_arguments(astmodulestate *state, PyObject* obj, arguments_ty* out,
             arg_ty val;
             PyObject *tmp2 = PyList_GET_ITEM(tmp, i);
             Py_INCREF(tmp2);
+            if (Py_EnterRecursiveCall(" while traversing 'arguments' node")) {
+                goto failed;
+            }
             res = obj2ast_arg(state, tmp2, &val, arena);
+            Py_LeaveRecursiveCall();
             Py_DECREF(tmp2);
             if (res != 0) goto failed;
             if (len != PyList_GET_SIZE(tmp)) {
@@ -9134,7 +9734,11 @@ obj2ast_arguments(astmodulestate *state, PyObject* obj, arguments_ty* out,
             arg_ty val;
             PyObject *tmp2 = PyList_GET_ITEM(tmp, i);
             Py_INCREF(tmp2);
+            if (Py_EnterRecursiveCall(" while traversing 'arguments' node")) {
+                goto failed;
+            }
             res = obj2ast_arg(state, tmp2, &val, arena);
+            Py_LeaveRecursiveCall();
             Py_DECREF(tmp2);
             if (res != 0) goto failed;
             if (len != PyList_GET_SIZE(tmp)) {
@@ -9154,7 +9758,11 @@ obj2ast_arguments(astmodulestate *state, PyObject* obj, arguments_ty* out,
     }
     else {
         int res;
+        if (Py_EnterRecursiveCall(" while traversing 'arguments' node")) {
+            goto failed;
+        }
         res = obj2ast_arg(state, tmp, &vararg, arena);
+        Py_LeaveRecursiveCall();
         if (res != 0) goto failed;
         Py_CLEAR(tmp);
     }
@@ -9180,7 +9788,11 @@ obj2ast_arguments(astmodulestate *state, PyObject* obj, arguments_ty* out,
             arg_ty val;
             PyObject *tmp2 = PyList_GET_ITEM(tmp, i);
             Py_INCREF(tmp2);
+            if (Py_EnterRecursiveCall(" while traversing 'arguments' node")) {
+                goto failed;
+            }
             res = obj2ast_arg(state, tmp2, &val, arena);
+            Py_LeaveRecursiveCall();
             Py_DECREF(tmp2);
             if (res != 0) goto failed;
             if (len != PyList_GET_SIZE(tmp)) {
@@ -9213,7 +9825,11 @@ obj2ast_arguments(astmodulestate *state, PyObject* obj, arguments_ty* out,
             expr_ty val;
             PyObject *tmp2 = PyList_GET_ITEM(tmp, i);
             Py_INCREF(tmp2);
+            if (Py_EnterRecursiveCall(" while traversing 'arguments' node")) {
+                goto failed;
+            }
             res = obj2ast_expr(state, tmp2, &val, arena);
+            Py_LeaveRecursiveCall();
             Py_DECREF(tmp2);
             if (res != 0) goto failed;
             if (len != PyList_GET_SIZE(tmp)) {
@@ -9233,7 +9849,11 @@ obj2ast_arguments(astmodulestate *state, PyObject* obj, arguments_ty* out,
     }
     else {
         int res;
+        if (Py_EnterRecursiveCall(" while traversing 'arguments' node")) {
+            goto failed;
+        }
         res = obj2ast_arg(state, tmp, &kwarg, arena);
+        Py_LeaveRecursiveCall();
         if (res != 0) goto failed;
         Py_CLEAR(tmp);
     }
@@ -9259,7 +9879,11 @@ obj2ast_arguments(astmodulestate *state, PyObject* obj, arguments_ty* out,
             expr_ty val;
             PyObject *tmp2 = PyList_GET_ITEM(tmp, i);
             Py_INCREF(tmp2);
+            if (Py_EnterRecursiveCall(" while traversing 'arguments' node")) {
+                goto failed;
+            }
             res = obj2ast_expr(state, tmp2, &val, arena);
+            Py_LeaveRecursiveCall();
             Py_DECREF(tmp2);
             if (res != 0) goto failed;
             if (len != PyList_GET_SIZE(tmp)) {
@@ -9299,7 +9923,11 @@ obj2ast_arg(astmodulestate *state, PyObject* obj, arg_ty* out, PyArena* arena)
     }
     else {
         int res;
+        if (Py_EnterRecursiveCall(" while traversing 'arg' node")) {
+            goto failed;
+        }
         res = obj2ast_identifier(state, tmp, &arg, arena);
+        Py_LeaveRecursiveCall();
         if (res != 0) goto failed;
         Py_CLEAR(tmp);
     }
@@ -9312,7 +9940,11 @@ obj2ast_arg(astmodulestate *state, PyObject* obj, arg_ty* out, PyArena* arena)
     }
     else {
         int res;
+        if (Py_EnterRecursiveCall(" while traversing 'arg' node")) {
+            goto failed;
+        }
         res = obj2ast_expr(state, tmp, &annotation, arena);
+        Py_LeaveRecursiveCall();
         if (res != 0) goto failed;
         Py_CLEAR(tmp);
     }
@@ -9325,7 +9957,11 @@ obj2ast_arg(astmodulestate *state, PyObject* obj, arg_ty* out, PyArena* arena)
     }
     else {
         int res;
+        if (Py_EnterRecursiveCall(" while traversing 'arg' node")) {
+            goto failed;
+        }
         res = obj2ast_string(state, tmp, &type_comment, arena);
+        Py_LeaveRecursiveCall();
         if (res != 0) goto failed;
         Py_CLEAR(tmp);
     }
@@ -9338,7 +9974,11 @@ obj2ast_arg(astmodulestate *state, PyObject* obj, arg_ty* out, PyArena* arena)
     }
     else {
         int res;
+        if (Py_EnterRecursiveCall(" while traversing 'arg' node")) {
+            goto failed;
+        }
         res = obj2ast_int(state, tmp, &lineno, arena);
+        Py_LeaveRecursiveCall();
         if (res != 0) goto failed;
         Py_CLEAR(tmp);
     }
@@ -9351,7 +9991,11 @@ obj2ast_arg(astmodulestate *state, PyObject* obj, arg_ty* out, PyArena* arena)
     }
     else {
         int res;
+        if (Py_EnterRecursiveCall(" while traversing 'arg' node")) {
+            goto failed;
+        }
         res = obj2ast_int(state, tmp, &col_offset, arena);
+        Py_LeaveRecursiveCall();
         if (res != 0) goto failed;
         Py_CLEAR(tmp);
     }
@@ -9364,7 +10008,11 @@ obj2ast_arg(astmodulestate *state, PyObject* obj, arg_ty* out, PyArena* arena)
     }
     else {
         int res;
+        if (Py_EnterRecursiveCall(" while traversing 'arg' node")) {
+            goto failed;
+        }
         res = obj2ast_int(state, tmp, &end_lineno, arena);
+        Py_LeaveRecursiveCall();
         if (res != 0) goto failed;
         Py_CLEAR(tmp);
     }
@@ -9377,7 +10025,11 @@ obj2ast_arg(astmodulestate *state, PyObject* obj, arg_ty* out, PyArena* arena)
     }
     else {
         int res;
+        if (Py_EnterRecursiveCall(" while traversing 'arg' node")) {
+            goto failed;
+        }
         res = obj2ast_int(state, tmp, &end_col_offset, arena);
+        Py_LeaveRecursiveCall();
         if (res != 0) goto failed;
         Py_CLEAR(tmp);
     }
@@ -9410,7 +10062,11 @@ obj2ast_keyword(astmodulestate *state, PyObject* obj, keyword_ty* out, PyArena*
     }
     else {
         int res;
+        if (Py_EnterRecursiveCall(" while traversing 'keyword' node")) {
+            goto failed;
+        }
         res = obj2ast_identifier(state, tmp, &arg, arena);
+        Py_LeaveRecursiveCall();
         if (res != 0) goto failed;
         Py_CLEAR(tmp);
     }
@@ -9423,7 +10079,11 @@ obj2ast_keyword(astmodulestate *state, PyObject* obj, keyword_ty* out, PyArena*
     }
     else {
         int res;
+        if (Py_EnterRecursiveCall(" while traversing 'keyword' node")) {
+            goto failed;
+        }
         res = obj2ast_expr(state, tmp, &value, arena);
+        Py_LeaveRecursiveCall();
         if (res != 0) goto failed;
         Py_CLEAR(tmp);
     }
@@ -9436,7 +10096,11 @@ obj2ast_keyword(astmodulestate *state, PyObject* obj, keyword_ty* out, PyArena*
     }
     else {
         int res;
+        if (Py_EnterRecursiveCall(" while traversing 'keyword' node")) {
+            goto failed;
+        }
         res = obj2ast_int(state, tmp, &lineno, arena);
+        Py_LeaveRecursiveCall();
         if (res != 0) goto failed;
         Py_CLEAR(tmp);
     }
@@ -9449,7 +10113,11 @@ obj2ast_keyword(astmodulestate *state, PyObject* obj, keyword_ty* out, PyArena*
     }
     else {
         int res;
+        if (Py_EnterRecursiveCall(" while traversing 'keyword' node")) {
+            goto failed;
+        }
         res = obj2ast_int(state, tmp, &col_offset, arena);
+        Py_LeaveRecursiveCall();
         if (res != 0) goto failed;
         Py_CLEAR(tmp);
     }
@@ -9462,7 +10130,11 @@ obj2ast_keyword(astmodulestate *state, PyObject* obj, keyword_ty* out, PyArena*
     }
     else {
         int res;
+        if (Py_EnterRecursiveCall(" while traversing 'keyword' node")) {
+            goto failed;
+        }
         res = obj2ast_int(state, tmp, &end_lineno, arena);
+        Py_LeaveRecursiveCall();
         if (res != 0) goto failed;
         Py_CLEAR(tmp);
     }
@@ -9475,7 +10147,11 @@ obj2ast_keyword(astmodulestate *state, PyObject* obj, keyword_ty* out, PyArena*
     }
     else {
         int res;
+        if (Py_EnterRecursiveCall(" while traversing 'keyword' node")) {
+            goto failed;
+        }
         res = obj2ast_int(state, tmp, &end_col_offset, arena);
+        Py_LeaveRecursiveCall();
         if (res != 0) goto failed;
         Py_CLEAR(tmp);
     }
@@ -9504,7 +10180,11 @@ obj2ast_alias(astmodulestate *state, PyObject* obj, alias_ty* out, PyArena*
     }
     else {
         int res;
+        if (Py_EnterRecursiveCall(" while traversing 'alias' node")) {
+            goto failed;
+        }
         res = obj2ast_identifier(state, tmp, &name, arena);
+        Py_LeaveRecursiveCall();
         if (res != 0) goto failed;
         Py_CLEAR(tmp);
     }
@@ -9517,7 +10197,11 @@ obj2ast_alias(astmodulestate *state, PyObject* obj, alias_ty* out, PyArena*
     }
     else {
         int res;
+        if (Py_EnterRecursiveCall(" while traversing 'alias' node")) {
+            goto failed;
+        }
         res = obj2ast_identifier(state, tmp, &asname, arena);
+        Py_LeaveRecursiveCall();
         if (res != 0) goto failed;
         Py_CLEAR(tmp);
     }
@@ -9545,7 +10229,11 @@ obj2ast_withitem(astmodulestate *state, PyObject* obj, withitem_ty* out,
     }
     else {
         int res;
+        if (Py_EnterRecursiveCall(" while traversing 'withitem' node")) {
+            goto failed;
+        }
         res = obj2ast_expr(state, tmp, &context_expr, arena);
+        Py_LeaveRecursiveCall();
         if (res != 0) goto failed;
         Py_CLEAR(tmp);
     }
@@ -9558,7 +10246,11 @@ obj2ast_withitem(astmodulestate *state, PyObject* obj, withitem_ty* out,
     }
     else {
         int res;
+        if (Py_EnterRecursiveCall(" while traversing 'withitem' node")) {
+            goto failed;
+        }
         res = obj2ast_expr(state, tmp, &optional_vars, arena);
+        Py_LeaveRecursiveCall();
         if (res != 0) goto failed;
         Py_CLEAR(tmp);
     }
@@ -9600,7 +10292,11 @@ obj2ast_type_ignore(astmodulestate *state, PyObject* obj, type_ignore_ty* out,
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'TypeIgnore' node")) {
+                goto failed;
+            }
             res = obj2ast_int(state, tmp, &lineno, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }
@@ -9613,7 +10309,11 @@ obj2ast_type_ignore(astmodulestate *state, PyObject* obj, type_ignore_ty* out,
         }
         else {
             int res;
+            if (Py_EnterRecursiveCall(" while traversing 'TypeIgnore' node")) {
+                goto failed;
+            }
             res = obj2ast_string(state, tmp, &tag, arena);
+            Py_LeaveRecursiveCall();
             if (res != 0) goto failed;
             Py_CLEAR(tmp);
         }