summaryrefslogtreecommitdiffstats
path: root/Parser
diff options
context:
space:
mode:
authorBatuhan Taskaya <batuhan@python.org>2021-06-03 21:22:34 (GMT)
committerGitHub <noreply@github.com>2021-06-03 21:22:34 (GMT)
commitde58b319af3a72440a74e807cf8a1194ed0c6d8c (patch)
tree09887cfcd1ad5428657f7747df04957dbc498b09 /Parser
parent5a8ddcc4524dca3880d7fc2818814ffae1cfb8a2 (diff)
downloadcpython-de58b319af3a72440a74e807cf8a1194ed0c6d8c.zip
cpython-de58b319af3a72440a74e807cf8a1194ed0c6d8c.tar.gz
cpython-de58b319af3a72440a74e807cf8a1194ed0c6d8c.tar.bz2
[3.9] bpo-11105: Do not crash when compiling recursive ASTs (GH-20594) (GH-26522)
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>
Diffstat (limited to 'Parser')
-rwxr-xr-xParser/asdl_c.py19
1 files changed, 15 insertions, 4 deletions
diff --git a/Parser/asdl_c.py b/Parser/asdl_c.py
index 6f3154a..4787050 100755
--- a/Parser/asdl_c.py
+++ b/Parser/asdl_c.py
@@ -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)