bpo-11105: Do not crash when compiling recursive ASTs (GH-20594) · python/cpython@f349124 (original) (raw)

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

`

6

6

`import textwrap

`

7

7

``

8

8

`from argparse import ArgumentParser

`

``

9

`+

from contextlib import contextmanager

`

9

10

`from pathlib import Path

`

10

11

``

11

12

`import asdl

`

`@@ -421,6 +422,14 @@ def visitProduct(self, prod, name):

`

421

422

``

422

423

``

423

424

`class Obj2ModVisitor(PickleVisitor):

`

``

425

`+

@contextmanager

`

``

426

`+

def recursive_call(self, node, level):

`

``

427

`+

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

`

``

428

`+

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

`

``

429

`+

self.emit('}', level)

`

``

430

`+

yield

`

``

431

`+

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

`

``

432

+

424

433

`def funcHeader(self, name):

`

425

434

`ctype = get_c_type(name)

`

426

435

`self.emit("int", 0)

`

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

`

596

605

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

`

597

606

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

`

598

607

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

`

599

``

`-

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

`

600

``

`-

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

`

``

608

`+

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

`

``

609

`+

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

`

``

610

`+

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

`

601

611

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

`

602

612

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

`

603

613

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

`

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

`

610

620

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

`

611

621

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

`

612

622

`else:

`

613

``

`-

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

`

614

``

`-

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

`

``

623

`+

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

`

``

624

`+

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

`

``

625

`+

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

`

615

626

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

`

616

627

``

617

628

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

`