From bcc30360951a303aa72b0502b77aad2c5f09f30d Mon Sep 17 00:00:00 2001 From: Pablo Galindo Date: Thu, 14 May 2020 21:11:48 +0100 Subject: bpo-40619: Correctly handle error lines in programs without file mode (GH-20090) --- Parser/pegen/pegen.c | 30 +++++------------------------- 1 file changed, 5 insertions(+), 25 deletions(-) (limited to 'Parser/pegen/pegen.c') diff --git a/Parser/pegen/pegen.c b/Parser/pegen/pegen.c index 083088bd96..8b79a73647 100644 --- a/Parser/pegen/pegen.c +++ b/Parser/pegen/pegen.c @@ -300,30 +300,6 @@ error: Py_XDECREF(tuple); } -static inline PyObject * -get_error_line(char *buffer, int is_file) -{ - const char *newline; - if (is_file) { - newline = strrchr(buffer, '\n'); - } else { - newline = strchr(buffer, '\n'); - } - - if (is_file) { - while (newline > buffer && newline[-1] == '\n') { - --newline; - } - } - - if (newline) { - return PyUnicode_DecodeUTF8(buffer, newline - buffer, "replace"); - } - else { - return PyUnicode_DecodeUTF8(buffer, strlen(buffer), "replace"); - } -} - static int tokenizer_error(Parser *p) { @@ -422,7 +398,11 @@ _PyPegen_raise_error_known_location(Parser *p, PyObject *errtype, } if (!error_line) { - error_line = get_error_line(p->tok->buf, p->start_rule == Py_file_input); + Py_ssize_t size = p->tok->inp - p->tok->buf; + if (size && p->tok->buf[size-1] == '\n') { + size--; + } + error_line = PyUnicode_DecodeUTF8(p->tok->buf, size, "replace"); if (!error_line) { goto error; } -- cgit v1.2.1 From 16ab07063cb564c1937714bd39d6915172f005b5 Mon Sep 17 00:00:00 2001 From: Pablo Galindo Date: Fri, 15 May 2020 02:04:52 +0100 Subject: bpo-40334: Correctly identify invalid target in assignment errors (GH-20076) Co-authored-by: Lysandros Nikolaou --- Parser/pegen/pegen.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) (limited to 'Parser/pegen/pegen.c') diff --git a/Parser/pegen/pegen.c b/Parser/pegen/pegen.c index 8b79a73647..7f3e4561de 100644 --- a/Parser/pegen/pegen.c +++ b/Parser/pegen/pegen.c @@ -2054,3 +2054,49 @@ _PyPegen_make_module(Parser *p, asdl_seq *a) { } return Module(a, type_ignores, p->arena); } + +// Error reporting helpers + +expr_ty +_PyPegen_get_invalid_target(expr_ty e) +{ + if (e == NULL) { + return NULL; + } + +#define VISIT_CONTAINER(CONTAINER, TYPE) do { \ + Py_ssize_t len = asdl_seq_LEN(CONTAINER->v.TYPE.elts);\ + for (Py_ssize_t i = 0; i < len; i++) {\ + expr_ty other = asdl_seq_GET(CONTAINER->v.TYPE.elts, i);\ + expr_ty child = _PyPegen_get_invalid_target(other);\ + if (child != NULL) {\ + return child;\ + }\ + }\ + } while (0) + + // We only need to visit List and Tuple nodes recursively as those + // are the only ones that can contain valid names in targets when + // they are parsed as expressions. Any other kind of expression + // that is a container (like Sets or Dicts) is directly invalid and + // we don't need to visit it recursively. + + switch (e->kind) { + case List_kind: { + VISIT_CONTAINER(e, List); + return NULL; + } + case Tuple_kind: { + VISIT_CONTAINER(e, Tuple); + return NULL; + } + case Starred_kind: + return _PyPegen_get_invalid_target(e->v.Starred.value); + case Name_kind: + case Subscript_kind: + case Attribute_kind: + return NULL; + default: + return e; + } +} \ No newline at end of file -- cgit v1.2.1