bpo-40870: Invalidate usage of some constants with ast.Name (GH-20649)

This commit is contained in:
Batuhan Taskaya 2020-06-06 15:44:16 +03:00 committed by GitHub
parent 5552850f8e
commit 68874a8502
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 31 additions and 0 deletions

View File

@ -668,6 +668,13 @@ class AST_Tests(unittest.TestCase):
with self.assertRaises(SyntaxError): with self.assertRaises(SyntaxError):
ast.parse('f"{x=}"', feature_version=(3, 7)) ast.parse('f"{x=}"', feature_version=(3, 7))
def test_constant_as_name(self):
for constant in "True", "False", "None":
expr = ast.Expression(ast.Name(constant, ast.Load()))
ast.fix_missing_locations(expr)
with self.assertRaisesRegex(ValueError, f"Name node can't be used with '{constant}' constant"):
compile(expr, "<test>", "eval")
class ASTHelpers_Test(unittest.TestCase): class ASTHelpers_Test(unittest.TestCase):
maxDiff = None maxDiff = None

View File

@ -0,0 +1,2 @@
Raise :exc:`ValueError` when validating custom AST's where the constants
``True``, ``False`` and ``None`` are used within a :class:`ast.Name` node.

View File

@ -21,6 +21,25 @@ static int validate_nonempty_seq(asdl_seq *, const char *, const char *);
static int validate_stmt(stmt_ty); static int validate_stmt(stmt_ty);
static int validate_expr(expr_ty, expr_context_ty); static int validate_expr(expr_ty, expr_context_ty);
static int
validate_name(PyObject *name)
{
assert(PyUnicode_Check(name));
static const char * const forbidden[] = {
"None",
"True",
"False",
NULL
};
for (int i = 0; forbidden[i] != NULL; i++) {
if (_PyUnicode_EqualToASCIIString(name, forbidden[i])) {
PyErr_Format(PyExc_ValueError, "Name node can't be used with '%s' constant", forbidden[i]);
return 0;
}
}
return 1;
}
static int static int
validate_comprehension(asdl_seq *gens) validate_comprehension(asdl_seq *gens)
{ {
@ -173,6 +192,9 @@ validate_expr(expr_ty exp, expr_context_ty ctx)
actual_ctx = exp->v.Starred.ctx; actual_ctx = exp->v.Starred.ctx;
break; break;
case Name_kind: case Name_kind:
if (!validate_name(exp->v.Name.id)) {
return 0;
}
actual_ctx = exp->v.Name.ctx; actual_ctx = exp->v.Name.ctx;
break; break;
case List_kind: case List_kind: