mirror of https://github.com/python/cpython
gh-92597: Ensure that AST nodes without explicit end positions can be compiled (GH-93359)
(cherry picked from commit 705eaec28f
)
Co-authored-by: Pablo Galindo Salgado <Pablogsal@gmail.com>
This commit is contained in:
parent
29bfabe970
commit
b425d887aa
|
@ -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
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
Ensure that custom :mod:`ast` nodes without explicit end positions can be
|
||||||
|
compiled. Patch by Pablo Galindo.
|
|
@ -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:
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue