From 44becb8cba677cbfdbcf2f7652277e5e1efc4f20 Mon Sep 17 00:00:00 2001 From: devdanzin <74280297+devdanzin@users.noreply.github.com> Date: Sat, 26 Oct 2024 22:23:53 -0300 Subject: [PATCH] gh-125666: Avoid PyREPL exiting when a null byte is in input (#125732) --- Lib/code.py | 3 ++- Lib/test/test_pyrepl/test_interact.py | 9 +++++++++ Lib/test/test_pyrepl/test_pyrepl.py | 5 +++++ .../2024-10-19-16-06-52.gh-issue-125666.jGfdCP.rst | 1 + 4 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Library/2024-10-19-16-06-52.gh-issue-125666.jGfdCP.rst diff --git a/Lib/code.py b/Lib/code.py index c7c59ee2021..1cc2ed8b1db 100644 --- a/Lib/code.py +++ b/Lib/code.py @@ -136,7 +136,8 @@ class InteractiveInterpreter: # 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 0c6df4e5dae..e0ee310e2c4 100644 --- a/Lib/test/test_pyrepl/test_interact.py +++ b/Lib/test/test_pyrepl/test_interact.py @@ -117,6 +117,15 @@ SyntaxError: duplicate argument 'x' in function definition""" 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), 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() source = dedent("""\ diff --git a/Lib/test/test_pyrepl/test_pyrepl.py b/Lib/test/test_pyrepl/test_pyrepl.py index 1a76832386b..f29a7ffbd7c 100644 --- a/Lib/test/test_pyrepl/test_pyrepl.py +++ b/Lib/test/test_pyrepl/test_pyrepl.py @@ -1313,6 +1313,11 @@ class TestMain(ReplTestCase): 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') 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 00000000000..3b4488815cc --- /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.