[3.9] bpo-11105: Do not crash when compiling recursive ASTs (GH-20594… · python/cpython@de58b31 (original) (raw)

`@@ -5,6 +5,7 @@

`

5

5

`import sys

`

6

6

``

7

7

`from argparse import ArgumentParser

`

``

8

`+

from contextlib import contextmanager

`

8

9

`from pathlib import Path

`

9

10

``

10

11

`import asdl

`

`@@ -394,6 +395,14 @@ def visitProduct(self, prod, name):

`

394

395

``

395

396

``

396

397

`class Obj2ModVisitor(PickleVisitor):

`

``

398

`+

@contextmanager

`

``

399

`+

def recursive_call(self, node, level):

`

``

400

`+

self.emit('if (Py_EnterRecursiveCall(" while traversing '%s' node")) {' % node, level, reflow=False)

`

``

401

`+

self.emit('goto failed;', level + 1)

`

``

402

`+

self.emit('}', level)

`

``

403

`+

yield

`

``

404

`+

self.emit('Py_LeaveRecursiveCall();', level)

`

``

405

+

397

406

`def funcHeader(self, name):

`

398

407

`ctype = get_c_type(name)

`

399

408

`self.emit("int", 0)

`

`@@ -568,8 +577,9 @@ def visitField(self, field, name, sum=None, prod=None, depth=0):

`

568

577

`self.emit("%s val;" % ctype, depth+2)

`

569

578

`self.emit("PyObject *tmp2 = PyList_GET_ITEM(tmp, i);", depth+2)

`

570

579

`self.emit("Py_INCREF(tmp2);", depth+2)

`

571

``

`-

self.emit("res = obj2ast_%s(state, tmp2, &val, arena);" %

`

572

``

`-

field.type, depth+2, reflow=False)

`

``

580

`+

with self.recursive_call(name, depth+2):

`

``

581

`+

self.emit("res = obj2ast_%s(state, tmp2, &val, arena);" %

`

``

582

`+

field.type, depth+2, reflow=False)

`

573

583

`self.emit("Py_DECREF(tmp2);", depth+2)

`

574

584

`self.emit("if (res != 0) goto failed;", depth+2)

`

575

585

`self.emit("if (len != PyList_GET_SIZE(tmp)) {", depth+2)

`

`@@ -582,8 +592,9 @@ def visitField(self, field, name, sum=None, prod=None, depth=0):

`

582

592

`self.emit("asdl_seq_SET(%s, i, val);" % field.name, depth+2)

`

583

593

`self.emit("}", depth+1)

`

584

594

`else:

`

585

``

`-

self.emit("res = obj2ast_%s(state, tmp, &%s, arena);" %

`

586

``

`-

(field.type, field.name), depth+1)

`

``

595

`+

with self.recursive_call(name, depth+1):

`

``

596

`+

self.emit("res = obj2ast_%s(state, tmp, &%s, arena);" %

`

``

597

`+

(field.type, field.name), depth+1)

`

587

598

`self.emit("if (res != 0) goto failed;", depth+1)

`

588

599

``

589

600

`self.emit("Py_CLEAR(tmp);", depth+1)

`