gh-92597: Ensure that AST nodes without explicit end positions can be compiled (GH-93359)

This commit is contained in:
Pablo Galindo Salgado 2022-06-01 00:00:47 +01:00 committed by GitHub
parent fc694364cc
commit 705eaec28f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 35 additions and 13 deletions

View File

@ -362,6 +362,14 @@ class AST_Tests(unittest.TestCase):
with self.assertRaises(ValueError): with self.assertRaises(ValueError):
compile(tree, '<string>', 'exec') compile(tree, '<string>', 'exec')
def test_compilation_of_ast_nodes_with_default_end_position_values(self):
tree = ast.Module(body=[
ast.Import(names=[ast.alias(name='builtins', lineno=1, col_offset=0)], lineno=1, col_offset=0),
ast.Import(names=[ast.alias(name='traceback', lineno=0, col_offset=0)], lineno=0, col_offset=1)
], type_ignores=[])
# Check that compilation doesn't crash. Note: this may crash explicitly only on debug mode.
compile(tree, "<string>", "exec")
def test_slice(self): def test_slice(self):
slc = ast.parse("x[::]").body[0].value.slice slc = ast.parse("x[::]").body[0].value.slice

View File

@ -0,0 +1,2 @@
Ensure that custom :mod:`ast` nodes without explicit end positions can be
compiled. Patch by Pablo Galindo.

View File

@ -488,6 +488,12 @@ class Obj2ModPrototypeVisitor(PickleVisitor):
class Obj2ModVisitor(PickleVisitor): class Obj2ModVisitor(PickleVisitor):
attribute_special_defaults = {
"end_lineno": "lineno",
"end_col_offset": "col_offset",
}
@contextmanager @contextmanager
def recursive_call(self, node, level): def recursive_call(self, node, level):
self.emit('if (_Py_EnterRecursiveCall(" while traversing \'%s\' node")) {' % node, level, reflow=False) self.emit('if (_Py_EnterRecursiveCall(" while traversing \'%s\' node")) {' % node, level, reflow=False)
@ -637,7 +643,13 @@ class Obj2ModVisitor(PickleVisitor):
self.emit("if (tmp == NULL || tmp == Py_None) {", depth) self.emit("if (tmp == NULL || tmp == Py_None) {", depth)
self.emit("Py_CLEAR(tmp);", depth+1) self.emit("Py_CLEAR(tmp);", depth+1)
if self.isNumeric(field): if self.isNumeric(field):
self.emit("%s = 0;" % field.name, depth+1) if field.name in self.attribute_special_defaults:
self.emit(
"%s = %s;" % (field.name, self.attribute_special_defaults[field.name]),
depth+1,
)
else:
self.emit("%s = 0;" % field.name, depth+1)
elif not self.isSimpleType(field): elif not self.isSimpleType(field):
self.emit("%s = NULL;" % field.name, depth+1) self.emit("%s = NULL;" % field.name, depth+1)
else: else:

24
Python/Python-ast.c generated
View File

@ -5697,7 +5697,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
} }
if (tmp == NULL || tmp == Py_None) { if (tmp == NULL || tmp == Py_None) {
Py_CLEAR(tmp); Py_CLEAR(tmp);
end_lineno = 0; end_lineno = lineno;
} }
else { else {
int res; int res;
@ -5714,7 +5714,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
} }
if (tmp == NULL || tmp == Py_None) { if (tmp == NULL || tmp == Py_None) {
Py_CLEAR(tmp); Py_CLEAR(tmp);
end_col_offset = 0; end_col_offset = col_offset;
} }
else { else {
int res; int res;
@ -8114,7 +8114,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*
} }
if (tmp == NULL || tmp == Py_None) { if (tmp == NULL || tmp == Py_None) {
Py_CLEAR(tmp); Py_CLEAR(tmp);
end_lineno = 0; end_lineno = lineno;
} }
else { else {
int res; int res;
@ -8131,7 +8131,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*
} }
if (tmp == NULL || tmp == Py_None) { if (tmp == NULL || tmp == Py_None) {
Py_CLEAR(tmp); Py_CLEAR(tmp);
end_col_offset = 0; end_col_offset = col_offset;
} }
else { else {
int res; int res;
@ -10291,7 +10291,7 @@ obj2ast_excepthandler(struct ast_state *state, PyObject* obj, excepthandler_ty*
} }
if (tmp == NULL || tmp == Py_None) { if (tmp == NULL || tmp == Py_None) {
Py_CLEAR(tmp); Py_CLEAR(tmp);
end_lineno = 0; end_lineno = lineno;
} }
else { else {
int res; int res;
@ -10308,7 +10308,7 @@ obj2ast_excepthandler(struct ast_state *state, PyObject* obj, excepthandler_ty*
} }
if (tmp == NULL || tmp == Py_None) { if (tmp == NULL || tmp == Py_None) {
Py_CLEAR(tmp); Py_CLEAR(tmp);
end_col_offset = 0; end_col_offset = col_offset;
} }
else { else {
int res; int res;
@ -10755,7 +10755,7 @@ obj2ast_arg(struct ast_state *state, PyObject* obj, arg_ty* out, PyArena* arena)
} }
if (tmp == NULL || tmp == Py_None) { if (tmp == NULL || tmp == Py_None) {
Py_CLEAR(tmp); Py_CLEAR(tmp);
end_lineno = 0; end_lineno = lineno;
} }
else { else {
int res; int res;
@ -10772,7 +10772,7 @@ obj2ast_arg(struct ast_state *state, PyObject* obj, arg_ty* out, PyArena* arena)
} }
if (tmp == NULL || tmp == Py_None) { if (tmp == NULL || tmp == Py_None) {
Py_CLEAR(tmp); Py_CLEAR(tmp);
end_col_offset = 0; end_col_offset = col_offset;
} }
else { else {
int res; int res;
@ -10877,7 +10877,7 @@ obj2ast_keyword(struct ast_state *state, PyObject* obj, keyword_ty* out,
} }
if (tmp == NULL || tmp == Py_None) { if (tmp == NULL || tmp == Py_None) {
Py_CLEAR(tmp); Py_CLEAR(tmp);
end_lineno = 0; end_lineno = lineno;
} }
else { else {
int res; int res;
@ -10894,7 +10894,7 @@ obj2ast_keyword(struct ast_state *state, PyObject* obj, keyword_ty* out,
} }
if (tmp == NULL || tmp == Py_None) { if (tmp == NULL || tmp == Py_None) {
Py_CLEAR(tmp); Py_CLEAR(tmp);
end_col_offset = 0; end_col_offset = col_offset;
} }
else { else {
int res; int res;
@ -10999,7 +10999,7 @@ obj2ast_alias(struct ast_state *state, PyObject* obj, alias_ty* out, PyArena*
} }
if (tmp == NULL || tmp == Py_None) { if (tmp == NULL || tmp == Py_None) {
Py_CLEAR(tmp); Py_CLEAR(tmp);
end_lineno = 0; end_lineno = lineno;
} }
else { else {
int res; int res;
@ -11016,7 +11016,7 @@ obj2ast_alias(struct ast_state *state, PyObject* obj, alias_ty* out, PyArena*
} }
if (tmp == NULL || tmp == Py_None) { if (tmp == NULL || tmp == Py_None) {
Py_CLEAR(tmp); Py_CLEAR(tmp);
end_col_offset = 0; end_col_offset = col_offset;
} }
else { else {
int res; int res;