for dfn in mod.dfns:
self.visit(dfn)
self.file.write(textwrap.dedent('''
+ state->recursion_depth = 0;
+ state->recursion_limit = 0;
state->initialized = 1;
return 1;
}
self.emit('if (!o) {', 1)
self.emit("Py_RETURN_NONE;", 2)
self.emit("}", 1)
+ self.emit("if (++state->recursion_depth > state->recursion_limit) {", 1)
+ self.emit("PyErr_SetString(PyExc_RecursionError,", 2)
+ self.emit('"maximum recursion depth exceeded during ast construction");', 3)
+ self.emit("return 0;", 2)
+ self.emit("}", 1)
def func_end(self):
+ self.emit("state->recursion_depth--;", 1)
self.emit("return result;", 1)
self.emit("failed:", 0)
self.emit("Py_XDECREF(value);", 1)
if (state == NULL) {
return NULL;
}
- return ast2obj_mod(state, t);
+
+ int recursion_limit = Py_GetRecursionLimit();
+ int starting_recursion_depth;
+ /* Be careful here to prevent overflow. */
+ int COMPILER_STACK_FRAME_SCALE = 3;
+ PyThreadState *tstate = _PyThreadState_GET();
+ if (!tstate) {
+ return 0;
+ }
+ state->recursion_limit = (recursion_limit < INT_MAX / COMPILER_STACK_FRAME_SCALE) ?
+ recursion_limit * COMPILER_STACK_FRAME_SCALE : recursion_limit;
+ int recursion_depth = tstate->recursion_limit - tstate->recursion_remaining;
+ starting_recursion_depth = (recursion_depth < INT_MAX / COMPILER_STACK_FRAME_SCALE) ?
+ recursion_depth * COMPILER_STACK_FRAME_SCALE : recursion_depth;
+ state->recursion_depth = starting_recursion_depth;
+
+ PyObject *result = ast2obj_mod(state, t);
+
+ /* Check that the recursion depth counting balanced correctly */
+ if (result && state->recursion_depth != starting_recursion_depth) {
+ PyErr_Format(PyExc_SystemError,
+ "AST constructor recursion depth mismatch (before=%d, after=%d)",
+ starting_recursion_depth, state->recursion_depth);
+ return 0;
+ }
+ return result;
}
/* mode is 0 for "exec", 1 for "eval" and 2 for "single" input */
def generate_ast_state(module_state, f):
f.write('struct ast_state {\n')
f.write(' int initialized;\n')
+ f.write(' int recursion_depth;\n')
+ f.write(' int recursion_limit;\n')
for s in module_state:
f.write(' PyObject *' + s + ';\n')
f.write('};')
"TypeIgnore(int lineno, string tag)");
if (!state->TypeIgnore_type) return 0;
+ state->recursion_depth = 0;
+ state->recursion_limit = 0;
state->initialized = 1;
return 1;
}
if (!o) {
Py_RETURN_NONE;
}
+ if (++state->recursion_depth > state->recursion_limit) {
+ PyErr_SetString(PyExc_RecursionError,
+ "maximum recursion depth exceeded during ast construction");
+ return 0;
+ }
switch (o->kind) {
case Module_kind:
tp = (PyTypeObject *)state->Module_type;
Py_DECREF(value);
break;
}
+ state->recursion_depth--;
return result;
failed:
Py_XDECREF(value);
if (!o) {
Py_RETURN_NONE;
}
+ if (++state->recursion_depth > state->recursion_limit) {
+ PyErr_SetString(PyExc_RecursionError,
+ "maximum recursion depth exceeded during ast construction");
+ return 0;
+ }
switch (o->kind) {
case FunctionDef_kind:
tp = (PyTypeObject *)state->FunctionDef_type;
if (PyObject_SetAttr(result, state->end_col_offset, value) < 0)
goto failed;
Py_DECREF(value);
+ state->recursion_depth--;
return result;
failed:
Py_XDECREF(value);
if (!o) {
Py_RETURN_NONE;
}
+ if (++state->recursion_depth > state->recursion_limit) {
+ PyErr_SetString(PyExc_RecursionError,
+ "maximum recursion depth exceeded during ast construction");
+ return 0;
+ }
switch (o->kind) {
case BoolOp_kind:
tp = (PyTypeObject *)state->BoolOp_type;
if (PyObject_SetAttr(result, state->end_col_offset, value) < 0)
goto failed;
Py_DECREF(value);
+ state->recursion_depth--;
return result;
failed:
Py_XDECREF(value);
if (!o) {
Py_RETURN_NONE;
}
+ if (++state->recursion_depth > state->recursion_limit) {
+ PyErr_SetString(PyExc_RecursionError,
+ "maximum recursion depth exceeded during ast construction");
+ return 0;
+ }
tp = (PyTypeObject *)state->comprehension_type;
result = PyType_GenericNew(tp, NULL, NULL);
if (!result) return NULL;
if (PyObject_SetAttr(result, state->is_async, value) == -1)
goto failed;
Py_DECREF(value);
+ state->recursion_depth--;
return result;
failed:
Py_XDECREF(value);
if (!o) {
Py_RETURN_NONE;
}
+ if (++state->recursion_depth > state->recursion_limit) {
+ PyErr_SetString(PyExc_RecursionError,
+ "maximum recursion depth exceeded during ast construction");
+ return 0;
+ }
switch (o->kind) {
case ExceptHandler_kind:
tp = (PyTypeObject *)state->ExceptHandler_type;
if (PyObject_SetAttr(result, state->end_col_offset, value) < 0)
goto failed;
Py_DECREF(value);
+ state->recursion_depth--;
return result;
failed:
Py_XDECREF(value);
if (!o) {
Py_RETURN_NONE;
}
+ if (++state->recursion_depth > state->recursion_limit) {
+ PyErr_SetString(PyExc_RecursionError,
+ "maximum recursion depth exceeded during ast construction");
+ return 0;
+ }
tp = (PyTypeObject *)state->arguments_type;
result = PyType_GenericNew(tp, NULL, NULL);
if (!result) return NULL;
if (PyObject_SetAttr(result, state->defaults, value) == -1)
goto failed;
Py_DECREF(value);
+ state->recursion_depth--;
return result;
failed:
Py_XDECREF(value);
if (!o) {
Py_RETURN_NONE;
}
+ if (++state->recursion_depth > state->recursion_limit) {
+ PyErr_SetString(PyExc_RecursionError,
+ "maximum recursion depth exceeded during ast construction");
+ return 0;
+ }
tp = (PyTypeObject *)state->arg_type;
result = PyType_GenericNew(tp, NULL, NULL);
if (!result) return NULL;
if (PyObject_SetAttr(result, state->end_col_offset, value) < 0)
goto failed;
Py_DECREF(value);
+ state->recursion_depth--;
return result;
failed:
Py_XDECREF(value);
if (!o) {
Py_RETURN_NONE;
}
+ if (++state->recursion_depth > state->recursion_limit) {
+ PyErr_SetString(PyExc_RecursionError,
+ "maximum recursion depth exceeded during ast construction");
+ return 0;
+ }
tp = (PyTypeObject *)state->keyword_type;
result = PyType_GenericNew(tp, NULL, NULL);
if (!result) return NULL;
if (PyObject_SetAttr(result, state->end_col_offset, value) < 0)
goto failed;
Py_DECREF(value);
+ state->recursion_depth--;
return result;
failed:
Py_XDECREF(value);
if (!o) {
Py_RETURN_NONE;
}
+ if (++state->recursion_depth > state->recursion_limit) {
+ PyErr_SetString(PyExc_RecursionError,
+ "maximum recursion depth exceeded during ast construction");
+ return 0;
+ }
tp = (PyTypeObject *)state->alias_type;
result = PyType_GenericNew(tp, NULL, NULL);
if (!result) return NULL;
if (PyObject_SetAttr(result, state->end_col_offset, value) < 0)
goto failed;
Py_DECREF(value);
+ state->recursion_depth--;
return result;
failed:
Py_XDECREF(value);
if (!o) {
Py_RETURN_NONE;
}
+ if (++state->recursion_depth > state->recursion_limit) {
+ PyErr_SetString(PyExc_RecursionError,
+ "maximum recursion depth exceeded during ast construction");
+ return 0;
+ }
tp = (PyTypeObject *)state->withitem_type;
result = PyType_GenericNew(tp, NULL, NULL);
if (!result) return NULL;
if (PyObject_SetAttr(result, state->optional_vars, value) == -1)
goto failed;
Py_DECREF(value);
+ state->recursion_depth--;
return result;
failed:
Py_XDECREF(value);
if (!o) {
Py_RETURN_NONE;
}
+ if (++state->recursion_depth > state->recursion_limit) {
+ PyErr_SetString(PyExc_RecursionError,
+ "maximum recursion depth exceeded during ast construction");
+ return 0;
+ }
tp = (PyTypeObject *)state->match_case_type;
result = PyType_GenericNew(tp, NULL, NULL);
if (!result) return NULL;
if (PyObject_SetAttr(result, state->body, value) == -1)
goto failed;
Py_DECREF(value);
+ state->recursion_depth--;
return result;
failed:
Py_XDECREF(value);
if (!o) {
Py_RETURN_NONE;
}
+ if (++state->recursion_depth > state->recursion_limit) {
+ PyErr_SetString(PyExc_RecursionError,
+ "maximum recursion depth exceeded during ast construction");
+ return 0;
+ }
switch (o->kind) {
case MatchValue_kind:
tp = (PyTypeObject *)state->MatchValue_type;
if (PyObject_SetAttr(result, state->end_col_offset, value) < 0)
goto failed;
Py_DECREF(value);
+ state->recursion_depth--;
return result;
failed:
Py_XDECREF(value);
if (!o) {
Py_RETURN_NONE;
}
+ if (++state->recursion_depth > state->recursion_limit) {
+ PyErr_SetString(PyExc_RecursionError,
+ "maximum recursion depth exceeded during ast construction");
+ return 0;
+ }
switch (o->kind) {
case TypeIgnore_kind:
tp = (PyTypeObject *)state->TypeIgnore_type;
Py_DECREF(value);
break;
}
+ state->recursion_depth--;
return result;
failed:
Py_XDECREF(value);
if (state == NULL) {
return NULL;
}
- return ast2obj_mod(state, t);
+
+ int recursion_limit = Py_GetRecursionLimit();
+ int starting_recursion_depth;
+ /* Be careful here to prevent overflow. */
+ int COMPILER_STACK_FRAME_SCALE = 3;
+ PyThreadState *tstate = _PyThreadState_GET();
+ if (!tstate) {
+ return 0;
+ }
+ state->recursion_limit = (recursion_limit < INT_MAX / COMPILER_STACK_FRAME_SCALE) ?
+ recursion_limit * COMPILER_STACK_FRAME_SCALE : recursion_limit;
+ int recursion_depth = tstate->recursion_limit - tstate->recursion_remaining;
+ starting_recursion_depth = (recursion_depth < INT_MAX / COMPILER_STACK_FRAME_SCALE) ?
+ recursion_depth * COMPILER_STACK_FRAME_SCALE : recursion_depth;
+ state->recursion_depth = starting_recursion_depth;
+
+ PyObject *result = ast2obj_mod(state, t);
+
+ /* Check that the recursion depth counting balanced correctly */
+ if (result && state->recursion_depth != starting_recursion_depth) {
+ PyErr_Format(PyExc_SystemError,
+ "AST constructor recursion depth mismatch (before=%d, after=%d)",
+ starting_recursion_depth, state->recursion_depth);
+ return 0;
+ }
+ return result;
}
/* mode is 0 for "exec", 1 for "eval" and 2 for "single" input */