diff options
author | Lysandros Nikolaou <lisandrosnik@gmail.com> | 2020-06-21 02:47:22 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-06-21 02:47:22 (GMT) |
commit | 71bb921829c33c30b2e111e18948df8c2b6731e4 (patch) | |
tree | cdcfa2d0ffed021c046d3dbc355fdeefa583b025 /Parser | |
parent | d301d9473e9a9b78d6e6678e9fe5ef66d46084e1 (diff) | |
download | cpython-71bb921829c33c30b2e111e18948df8c2b6731e4.zip cpython-71bb921829c33c30b2e111e18948df8c2b6731e4.tar.gz cpython-71bb921829c33c30b2e111e18948df8c2b6731e4.tar.bz2 |
[3.9] bpo-41060: Avoid SEGFAULT when calling GET_INVALID_TARGET in the grammar (GH-21020) (GH-21024)
`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.
(cherry picked from commit 6c4e0bd974f2895d42b63d9d004587e74b286c88)
Automerge-Triggered-By: @pablogsal
Diffstat (limited to 'Parser')
-rw-r--r-- | Parser/pegen/parse.c | 8 | ||||
-rw-r--r-- | Parser/pegen/pegen.h | 25 |
2 files changed, 26 insertions, 7 deletions
diff --git a/Parser/pegen/parse.c b/Parser/pegen/parse.c index b105715..9f034ab 100644 --- a/Parser/pegen/parse.c +++ b/Parser/pegen/parse.c @@ -14852,7 +14852,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 '='")); - _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()) { p->error_indicator = 1; D(p->level--); @@ -14956,7 +14956,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")); - _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()) { p->error_indicator = 1; D(p->level--); @@ -15413,7 +15413,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")); - _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()) { p->error_indicator = 1; D(p->level--); @@ -15461,7 +15461,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")); - _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()) { p->error_indicator = 1; D(p->level--); diff --git a/Parser/pegen/pegen.h b/Parser/pegen/pegen.h index 1c038ab..361b671 100644 --- a/Parser/pegen/pegen.h +++ b/Parser/pegen/pegen.h @@ -269,9 +269,28 @@ typedef enum { FOR_TARGETS } 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 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)) +#define RAISE_SYNTAX_ERROR_INVALID_TARGET(type, e) _RAISE_SYNTAX_ERROR_INVALID_TARGET(p, type, e) + +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_nonparen_genexp_in_call(Parser *p, expr_ty args); |