From f6f48a5342d0abce75e0adaced112d446041d147 Mon Sep 17 00:00:00 2001 From: Pablo Galindo Date: Thu, 18 Nov 2021 19:14:57 +0000 Subject: [PATCH 1/2] Delimitate when source lines can't be located in the parser error handling functions --- Parser/pegen.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Parser/pegen.c b/Parser/pegen.c index 15879a64f279cf..9e57c3db4a8050 100644 --- a/Parser/pegen.c +++ b/Parser/pegen.c @@ -504,9 +504,12 @@ _PyPegen_raise_error_known_location(Parser *p, PyObject *errtype, Py_ssize_t size = p->tok->inp - p->tok->buf; error_line = PyUnicode_DecodeUTF8(p->tok->buf, size, "replace"); } - else { + else if (p->tok->fp == NULL || p->tok->fp == stdin) { error_line = get_error_line(p, lineno); } + else { + error_line = PyUnicode_FromStringAndSize("", 0); + } if (!error_line) { goto error; } From d2980b7e994979c8db7dbc7e6066f9d31d1f6e21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Langa?= Date: Fri, 19 Nov 2021 20:37:17 +0100 Subject: [PATCH 2/2] Add test --- Lib/test/test_peg_generator/test_c_parser.py | 36 +++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_peg_generator/test_c_parser.py b/Lib/test/test_peg_generator/test_c_parser.py index b761bd493f52c7..90d865ee64794c 100644 --- a/Lib/test/test_peg_generator/test_c_parser.py +++ b/Lib/test/test_peg_generator/test_c_parser.py @@ -9,7 +9,7 @@ from test import test_tools from test import support from test.support import os_helper -from test.support.script_helper import assert_python_ok +from test.support.script_helper import assert_python_ok, run_python_until_end _py_cflags_nodist = sysconfig.get_config_var("PY_CFLAGS_NODIST") _pgo_flag = sysconfig.get_config_var("PGO_PROF_USE_FLAG") @@ -483,3 +483,37 @@ def test_forced_with_group(self) -> None: self.assertIn("expected (':' | ';')", e.exception.args[0]) """ self.run_test(grammar_source, test_source) + + +class TestCPythonParserEdgeCases(unittest.TestCase): + def setUp(self): + self.tmp_path = tempfile.mkdtemp() + change_cwd = os_helper.change_cwd(self.tmp_path) + change_cwd.__enter__() + self.addCleanup(change_cwd.__exit__, None, None, None) + self.addCleanup(shutil.rmtree, self.tmp_path) + + def assert_python( + self, test_source, expected="", not_expected="", encoding="utf8" + ): + test_source = textwrap.dedent(test_source) + with tempfile.NamedTemporaryFile(dir=self.tmp_path, suffix=".py") as f: + f.write(test_source.encode(encoding)) + f.flush() + result, _cmdline = run_python_until_end(f.name) + _rc, out_b, err_b = result + output = out_b.decode() + "\n" + err_b.decode() + if not_expected: + self.assertNotIn(not_expected, output) + if expected: + self.assertIn(expected, output) + + def test_encoding_cookie(self): + self.assert_python( + """ + # encoding: ascii + ( + """, + expected="'(' was never closed", + not_expected="Fatal Python error: Aborted", + )