From aa971bb2ee744849a29b4dd4c570e203ed324ef1 Mon Sep 17 00:00:00 2001 From: devdanzin <74280297+devdanzin@users.noreply.github.com> Date: Sat, 19 Oct 2024 12:29:48 -0300 Subject: [PATCH 1/4] Guard against SyntaxError.lineno being None in code.InteractiveInterpreter._showtraceback. --- Lib/code.py | 3 ++- Lib/test/test_pyrepl/test_interact.py | 8 ++++++++ Lib/test/test_pyrepl/test_pyrepl.py | 5 +++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/Lib/code.py b/Lib/code.py index c7c59ee20219c5..1cc2ed8b1dbf28 100644 --- a/Lib/code.py +++ b/Lib/code.py @@ -136,7 +136,8 @@ def _showtraceback(self, typ, value, tb, source): # Set the line of text that the exception refers to lines = source.splitlines() if (source and typ is SyntaxError - and not value.text and len(lines) >= value.lineno): + and not value.text and value.lineno is not None + and len(lines) >= value.lineno): value.text = lines[value.lineno - 1] sys.last_exc = sys.last_value = value if sys.excepthook is sys.__excepthook__: diff --git a/Lib/test/test_pyrepl/test_interact.py b/Lib/test/test_pyrepl/test_interact.py index 0c6df4e5dae869..b1399adaaeab6a 100644 --- a/Lib/test/test_pyrepl/test_interact.py +++ b/Lib/test/test_pyrepl/test_interact.py @@ -117,6 +117,14 @@ def test_runsource_shows_syntax_error_for_failed_compilation(self): console.runsource(source) mock_showsyntaxerror.assert_called_once() + def test_runsource_survives_null_bytes(self): + console = InteractiveColoredConsole() + source = "\x00\n" + f = io.StringIO() + with contextlib.redirect_stdout(f): + result = console.runsource(source) + self.assertFalse(result) + def test_no_active_future(self): console = InteractiveColoredConsole() source = dedent("""\ diff --git a/Lib/test/test_pyrepl/test_pyrepl.py b/Lib/test/test_pyrepl/test_pyrepl.py index 1a76832386bf1d..f29a7ffbd7cafd 100644 --- a/Lib/test/test_pyrepl/test_pyrepl.py +++ b/Lib/test/test_pyrepl/test_pyrepl.py @@ -1313,6 +1313,11 @@ def test_proper_tracebacklimit(self): self.assertIn("in x3", output) self.assertIn("in ", output) + def test_null_byte(self): + output, exit_code = self.run_repl("\x00\nexit()\n") + self.assertEqual(exit_code, 0) + self.assertNotIn("TypeError", output) + def test_readline_history_file(self): # skip, if readline module is not available readline = import_module('readline') From a866e56884ea93e26f585c36d7b59e3c7119166a Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Sat, 19 Oct 2024 16:06:57 +0000 Subject: [PATCH 2/4] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20blu?= =?UTF-8?q?rb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../next/Library/2024-10-19-16-06-52.gh-issue-125666.jGfdCP.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Library/2024-10-19-16-06-52.gh-issue-125666.jGfdCP.rst diff --git a/Misc/NEWS.d/next/Library/2024-10-19-16-06-52.gh-issue-125666.jGfdCP.rst b/Misc/NEWS.d/next/Library/2024-10-19-16-06-52.gh-issue-125666.jGfdCP.rst new file mode 100644 index 00000000000000..3b4488815cced6 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-10-19-16-06-52.gh-issue-125666.jGfdCP.rst @@ -0,0 +1 @@ +Avoid the exiting the interpreter if a null byte is given as input in the new REPL. From a61b55186bba551ffcfd6d759e141a02619cbdb2 Mon Sep 17 00:00:00 2001 From: devdanzin <74280297+devdanzin@users.noreply.github.com> Date: Sat, 19 Oct 2024 13:11:16 -0300 Subject: [PATCH 3/4] Also redirect stderr in test_runsource_survives_null_bytes. --- Lib/test/test_pyrepl/test_interact.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_pyrepl/test_interact.py b/Lib/test/test_pyrepl/test_interact.py index b1399adaaeab6a..b5f2906aff2c10 100644 --- a/Lib/test/test_pyrepl/test_interact.py +++ b/Lib/test/test_pyrepl/test_interact.py @@ -122,8 +122,10 @@ def test_runsource_survives_null_bytes(self): source = "\x00\n" f = io.StringIO() with contextlib.redirect_stdout(f): - result = console.runsource(source) + with contextlib.redirect_stderr(f): + result = console.runsource(source) self.assertFalse(result) + self.assertIn("source code string cannot contain null bytes", f.getvalue()) def test_no_active_future(self): console = InteractiveColoredConsole() From 2502ded6cf11fb2d61fb36b08b6a1d0f2f72c931 Mon Sep 17 00:00:00 2001 From: Pablo Galindo Salgado Date: Sun, 27 Oct 2024 01:53:51 +0100 Subject: [PATCH 4/4] Update Lib/test/test_pyrepl/test_interact.py --- Lib/test/test_pyrepl/test_interact.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_pyrepl/test_interact.py b/Lib/test/test_pyrepl/test_interact.py index b5f2906aff2c10..e0ee310e2c4dbc 100644 --- a/Lib/test/test_pyrepl/test_interact.py +++ b/Lib/test/test_pyrepl/test_interact.py @@ -121,9 +121,8 @@ def test_runsource_survives_null_bytes(self): console = InteractiveColoredConsole() source = "\x00\n" f = io.StringIO() - with contextlib.redirect_stdout(f): - with contextlib.redirect_stderr(f): - result = console.runsource(source) + with contextlib.redirect_stdout(f), contextlib.redirect_stderr(f): + result = console.runsource(source) self.assertFalse(result) self.assertIn("source code string cannot contain null bytes", f.getvalue())