Skip to content

Commit 515a5d3

Browse files
Eclips4sobolevn
andauthored
[3.12] pythongh-126105: Fix crash in ast module, when ._fields is delet… (python#126132)
[3.12] pythongh-126105: Fix crash in `ast` module, when `._fields` is deleted (pythonGH-126115) Previously, if the `ast.AST._fields` attribute was deleted, attempts to create a new `as`t node would crash due to the assumption that `_fields` always had a non-NULL value. Now it has been fixed by adding an extra check to ensure that `_fields` does not have a NULL value (this can happen when you manually remove `_fields` attribute). (cherry picked from commit b2eaa75) Co-authored-by: sobolevn <[email protected]>
1 parent bce9df9 commit 515a5d3

File tree

4 files changed

+32
-12
lines changed

4 files changed

+32
-12
lines changed

Lib/test/test_ast/test_ast.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,23 @@ def test_AST_objects(self):
6666
# "ast.AST constructor takes 0 positional arguments"
6767
ast.AST(2)
6868

69+
def test_AST_fields_NULL_check(self):
70+
# See: https://github.com/python/cpython/issues/126105
71+
old_value = ast.AST._fields
72+
73+
def cleanup():
74+
ast.AST._fields = old_value
75+
self.addCleanup(cleanup)
76+
77+
del ast.AST._fields
78+
79+
msg = "type object 'ast.AST' has no attribute '_fields'"
80+
# Both examples used to crash:
81+
with self.assertRaisesRegex(AttributeError, msg):
82+
ast.AST(arg1=123)
83+
with self.assertRaisesRegex(AttributeError, msg):
84+
ast.AST()
85+
6986
def test_AST_garbage_collection(self):
7087
class X:
7188
pass
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix a crash in :mod:`ast` when the :attr:`ast.AST._fields` attribute is deleted.

Parser/asdl_c.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -813,14 +813,15 @@ def visitModule(self, mod):
813813
Py_ssize_t i, numfields = 0;
814814
int res = -1;
815815
PyObject *key, *value, *fields;
816-
if (_PyObject_LookupAttr((PyObject*)Py_TYPE(self), state->_fields, &fields) < 0) {
816+
817+
fields = PyObject_GetAttr((PyObject*)Py_TYPE(self), state->_fields);
818+
if (fields == NULL) {
817819
goto cleanup;
818820
}
819-
if (fields) {
820-
numfields = PySequence_Size(fields);
821-
if (numfields == -1) {
822-
goto cleanup;
823-
}
821+
822+
numfields = PySequence_Size(fields);
823+
if (numfields == -1) {
824+
goto cleanup;
824825
}
825826
826827
res = 0; /* if no error occurs, this stays 0 to the end */

Python/Python-ast.c

Lines changed: 7 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)