mirror of
https://github.com/python/cpython.git
synced 2025-12-23 09:19:18 +00:00
[3.9] bpo-46110: Add a recursion check to avoid stack overflow in the PEG parser (GH-30177) (#30215)
Co-authored-by: Batuhan Taskaya <isidentical@gmail.com>.
(cherry picked from commit e9898bf153)
Co-authored-by: Pablo Galindo Salgado <Pablogsal@gmail.com>
This commit is contained in:
parent
8e4564d14a
commit
e5cf31d3c2
4 changed files with 3329 additions and 2320 deletions
|
|
@ -1004,6 +1004,14 @@ while 1:
|
|||
"""
|
||||
self._check_error(source, "too many statically nested blocks")
|
||||
|
||||
@support.cpython_only
|
||||
def test_error_on_parser_stack_overflow(self):
|
||||
source = "-" * 100000 + "4"
|
||||
for mode in ["exec", "eval", "single"]:
|
||||
with self.subTest(mode=mode):
|
||||
with self.assertRaises(MemoryError):
|
||||
compile(source, "<string>", mode)
|
||||
|
||||
|
||||
def test_main():
|
||||
support.run_unittest(SyntaxTestCase)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
Add a maximum recursion check to the PEG parser to avoid stack overflow.
|
||||
Patch by Pablo Galindo
|
||||
5624
Parser/pegen/parse.c
5624
Parser/pegen/parse.c
File diff suppressed because it is too large
Load diff
|
|
@ -37,6 +37,8 @@ extern int Py_DebugFlag;
|
|||
#define D(x)
|
||||
#endif
|
||||
|
||||
# define MAXSTACK 6000
|
||||
|
||||
"""
|
||||
|
||||
|
||||
|
|
@ -331,10 +333,14 @@ class CParserGenerator(ParserGenerator, GrammarVisitor):
|
|||
self.skip_actions = skip_actions
|
||||
|
||||
def add_level(self) -> None:
|
||||
self.print("D(p->level++);")
|
||||
self.print("if (p->level++ == MAXSTACK) {")
|
||||
with self.indent():
|
||||
self.print("p->error_indicator = 1;")
|
||||
self.print("PyErr_NoMemory();")
|
||||
self.print("}")
|
||||
|
||||
def remove_level(self) -> None:
|
||||
self.print("D(p->level--);")
|
||||
self.print("p->level--;")
|
||||
|
||||
def add_return(self, ret_val: str) -> None:
|
||||
self.remove_level()
|
||||
|
|
@ -498,9 +504,10 @@ class CParserGenerator(ParserGenerator, GrammarVisitor):
|
|||
)
|
||||
self.print("p->mark = _mark;")
|
||||
self.print(f"void *_raw = {node.name}_raw(p);")
|
||||
self.print("if (p->error_indicator)")
|
||||
self.print("if (p->error_indicator) {")
|
||||
with self.indent():
|
||||
self.print("return NULL;")
|
||||
self.add_return("NULL")
|
||||
self.print("}")
|
||||
self.print("if (_raw == NULL || p->mark <= _resmark)")
|
||||
with self.indent():
|
||||
self.print("break;")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue