mirror of https://github.com/python/cpython
bpo-41060: Avoid SEGFAULT when calling GET_INVALID_TARGET in the grammar (GH-21020)
`GET_INVALID_TARGET` might unexpectedly return `NULL`, which if not caught will cause a SEGFAULT. Therefore, this commit introduces a new inline function `RAISE_SYNTAX_ERROR_INVALID_TARGET` that always checks for `GET_INVALID_TARGET` returning NULL and can be used in the grammar, replacing the long C ternary operation used till now.
This commit is contained in:
parent
3ccb96c978
commit
6c4e0bd974
|
@ -653,9 +653,7 @@ invalid_assignment:
|
||||||
| a=expression ':' expression ['=' annotated_rhs] {
|
| a=expression ':' expression ['=' annotated_rhs] {
|
||||||
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "illegal target for annotation") }
|
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "illegal target for annotation") }
|
||||||
| (star_targets '=')* a=star_expressions '=' {
|
| (star_targets '=')* a=star_expressions '=' {
|
||||||
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(
|
RAISE_SYNTAX_ERROR_INVALID_TARGET(STAR_TARGETS, a) }
|
||||||
GET_INVALID_TARGET(a),
|
|
||||||
"cannot assign to %s", _PyPegen_get_expr_name(GET_INVALID_TARGET(a))) }
|
|
||||||
| (star_targets '=')* a=yield_expr '=' { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "assignment to yield expression not possible") }
|
| (star_targets '=')* a=yield_expr '=' { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "assignment to yield expression not possible") }
|
||||||
| a=star_expressions augassign (yield_expr | star_expressions) {
|
| a=star_expressions augassign (yield_expr | star_expressions) {
|
||||||
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(
|
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(
|
||||||
|
@ -665,12 +663,7 @@ invalid_assignment:
|
||||||
)}
|
)}
|
||||||
invalid_del_stmt:
|
invalid_del_stmt:
|
||||||
| 'del' a=star_expressions {
|
| 'del' a=star_expressions {
|
||||||
GET_INVALID_DEL_TARGET(a) != NULL ?
|
RAISE_SYNTAX_ERROR_INVALID_TARGET(DEL_TARGETS, a) }
|
||||||
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(
|
|
||||||
GET_INVALID_DEL_TARGET(a),
|
|
||||||
"cannot delete %s", _PyPegen_get_expr_name(GET_INVALID_DEL_TARGET(a))
|
|
||||||
) :
|
|
||||||
RAISE_SYNTAX_ERROR("invalid syntax") }
|
|
||||||
invalid_block:
|
invalid_block:
|
||||||
| NEWLINE !INDENT { RAISE_INDENTATION_ERROR("expected an indented block") }
|
| NEWLINE !INDENT { RAISE_INDENTATION_ERROR("expected an indented block") }
|
||||||
invalid_comprehension:
|
invalid_comprehension:
|
||||||
|
@ -695,19 +688,11 @@ invalid_double_type_comments:
|
||||||
RAISE_SYNTAX_ERROR("Cannot have two type comments on def") }
|
RAISE_SYNTAX_ERROR("Cannot have two type comments on def") }
|
||||||
invalid_with_item:
|
invalid_with_item:
|
||||||
| expression 'as' a=expression {
|
| expression 'as' a=expression {
|
||||||
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(
|
RAISE_SYNTAX_ERROR_INVALID_TARGET(STAR_TARGETS, a) }
|
||||||
GET_INVALID_TARGET(a),
|
|
||||||
"cannot assign to %s", _PyPegen_get_expr_name(GET_INVALID_TARGET(a))
|
|
||||||
) }
|
|
||||||
|
|
||||||
invalid_for_target:
|
invalid_for_target:
|
||||||
| ASYNC? 'for' a=star_expressions {
|
| ASYNC? 'for' a=star_expressions {
|
||||||
GET_INVALID_FOR_TARGET(a) != NULL ?
|
RAISE_SYNTAX_ERROR_INVALID_TARGET(FOR_TARGETS, a) }
|
||||||
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(
|
|
||||||
GET_INVALID_FOR_TARGET(a),
|
|
||||||
"cannot assign to %s", _PyPegen_get_expr_name(GET_INVALID_FOR_TARGET(a))
|
|
||||||
) :
|
|
||||||
RAISE_SYNTAX_ERROR("invalid syntax") }
|
|
||||||
|
|
||||||
invalid_group:
|
invalid_group:
|
||||||
| '(' a=starred_expression ')' {
|
| '(' a=starred_expression ')' {
|
||||||
|
|
|
@ -199,6 +199,10 @@ SyntaxError: cannot assign to operator
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
SyntaxError: invalid syntax
|
SyntaxError: invalid syntax
|
||||||
|
|
||||||
|
>>> for a, b
|
||||||
|
Traceback (most recent call last):
|
||||||
|
SyntaxError: invalid syntax
|
||||||
|
|
||||||
>>> with a as b(): pass
|
>>> with a as b(): pass
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
SyntaxError: cannot assign to function call
|
SyntaxError: cannot assign to function call
|
||||||
|
@ -223,6 +227,10 @@ SyntaxError: cannot assign to function call
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
SyntaxError: cannot assign to function call
|
SyntaxError: cannot assign to function call
|
||||||
|
|
||||||
|
>>> with a as b
|
||||||
|
Traceback (most recent call last):
|
||||||
|
SyntaxError: invalid syntax
|
||||||
|
|
||||||
>>> p = p =
|
>>> p = p =
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
SyntaxError: invalid syntax
|
SyntaxError: invalid syntax
|
||||||
|
|
|
@ -14818,7 +14818,7 @@ invalid_assignment_rule(Parser *p)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
D(fprintf(stderr, "%*c+ invalid_assignment[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "((star_targets '='))* star_expressions '='"));
|
D(fprintf(stderr, "%*c+ invalid_assignment[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "((star_targets '='))* star_expressions '='"));
|
||||||
_res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( GET_INVALID_TARGET ( a ) , "cannot assign to %s" , _PyPegen_get_expr_name ( GET_INVALID_TARGET ( a ) ) );
|
_res = RAISE_SYNTAX_ERROR_INVALID_TARGET ( STAR_TARGETS , a );
|
||||||
if (_res == NULL && PyErr_Occurred()) {
|
if (_res == NULL && PyErr_Occurred()) {
|
||||||
p->error_indicator = 1;
|
p->error_indicator = 1;
|
||||||
D(p->level--);
|
D(p->level--);
|
||||||
|
@ -14922,7 +14922,7 @@ invalid_del_stmt_rule(Parser *p)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
D(fprintf(stderr, "%*c+ invalid_del_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'del' star_expressions"));
|
D(fprintf(stderr, "%*c+ invalid_del_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'del' star_expressions"));
|
||||||
_res = GET_INVALID_DEL_TARGET ( a ) != NULL ? RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( GET_INVALID_DEL_TARGET ( a ) , "cannot delete %s" , _PyPegen_get_expr_name ( GET_INVALID_DEL_TARGET ( a ) ) ) : RAISE_SYNTAX_ERROR ( "invalid syntax" );
|
_res = RAISE_SYNTAX_ERROR_INVALID_TARGET ( DEL_TARGETS , a );
|
||||||
if (_res == NULL && PyErr_Occurred()) {
|
if (_res == NULL && PyErr_Occurred()) {
|
||||||
p->error_indicator = 1;
|
p->error_indicator = 1;
|
||||||
D(p->level--);
|
D(p->level--);
|
||||||
|
@ -15379,7 +15379,7 @@ invalid_with_item_rule(Parser *p)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
D(fprintf(stderr, "%*c+ invalid_with_item[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression 'as' expression"));
|
D(fprintf(stderr, "%*c+ invalid_with_item[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression 'as' expression"));
|
||||||
_res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( GET_INVALID_TARGET ( a ) , "cannot assign to %s" , _PyPegen_get_expr_name ( GET_INVALID_TARGET ( a ) ) );
|
_res = RAISE_SYNTAX_ERROR_INVALID_TARGET ( STAR_TARGETS , a );
|
||||||
if (_res == NULL && PyErr_Occurred()) {
|
if (_res == NULL && PyErr_Occurred()) {
|
||||||
p->error_indicator = 1;
|
p->error_indicator = 1;
|
||||||
D(p->level--);
|
D(p->level--);
|
||||||
|
@ -15427,7 +15427,7 @@ invalid_for_target_rule(Parser *p)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
D(fprintf(stderr, "%*c+ invalid_for_target[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "ASYNC? 'for' star_expressions"));
|
D(fprintf(stderr, "%*c+ invalid_for_target[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "ASYNC? 'for' star_expressions"));
|
||||||
_res = GET_INVALID_FOR_TARGET ( a ) != NULL ? RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( GET_INVALID_FOR_TARGET ( a ) , "cannot assign to %s" , _PyPegen_get_expr_name ( GET_INVALID_FOR_TARGET ( a ) ) ) : RAISE_SYNTAX_ERROR ( "invalid syntax" );
|
_res = RAISE_SYNTAX_ERROR_INVALID_TARGET ( FOR_TARGETS , a );
|
||||||
if (_res == NULL && PyErr_Occurred()) {
|
if (_res == NULL && PyErr_Occurred()) {
|
||||||
p->error_indicator = 1;
|
p->error_indicator = 1;
|
||||||
D(p->level--);
|
D(p->level--);
|
||||||
|
|
|
@ -269,9 +269,28 @@ typedef enum {
|
||||||
FOR_TARGETS
|
FOR_TARGETS
|
||||||
} TARGETS_TYPE;
|
} TARGETS_TYPE;
|
||||||
expr_ty _PyPegen_get_invalid_target(expr_ty e, TARGETS_TYPE targets_type);
|
expr_ty _PyPegen_get_invalid_target(expr_ty e, TARGETS_TYPE targets_type);
|
||||||
#define GET_INVALID_TARGET(e) (expr_ty)CHECK(_PyPegen_get_invalid_target(e, STAR_TARGETS))
|
#define RAISE_SYNTAX_ERROR_INVALID_TARGET(type, e) _RAISE_SYNTAX_ERROR_INVALID_TARGET(p, type, e)
|
||||||
#define GET_INVALID_DEL_TARGET(e) (expr_ty)CHECK_NULL_ALLOWED(_PyPegen_get_invalid_target(e, DEL_TARGETS))
|
|
||||||
#define GET_INVALID_FOR_TARGET(e) (expr_ty)CHECK_NULL_ALLOWED(_PyPegen_get_invalid_target(e, FOR_TARGETS))
|
Py_LOCAL_INLINE(void *)
|
||||||
|
_RAISE_SYNTAX_ERROR_INVALID_TARGET(Parser *p, TARGETS_TYPE type, void *e)
|
||||||
|
{
|
||||||
|
expr_ty invalid_target = CHECK_NULL_ALLOWED(_PyPegen_get_invalid_target(e, type));
|
||||||
|
if (invalid_target != NULL) {
|
||||||
|
const char *msg;
|
||||||
|
if (type == STAR_TARGETS || type == FOR_TARGETS) {
|
||||||
|
msg = "cannot assign to %s";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
msg = "cannot delete %s";
|
||||||
|
}
|
||||||
|
return RAISE_SYNTAX_ERROR_KNOWN_LOCATION(
|
||||||
|
invalid_target,
|
||||||
|
msg,
|
||||||
|
_PyPegen_get_expr_name(invalid_target)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return RAISE_SYNTAX_ERROR("invalid syntax");
|
||||||
|
}
|
||||||
|
|
||||||
void *_PyPegen_arguments_parsing_error(Parser *, expr_ty);
|
void *_PyPegen_arguments_parsing_error(Parser *, expr_ty);
|
||||||
void *_PyPegen_nonparen_genexp_in_call(Parser *p, expr_ty args);
|
void *_PyPegen_nonparen_genexp_in_call(Parser *p, expr_ty args);
|
||||||
|
|
Loading…
Reference in New Issue