summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Lib/test/test_builtin.py44
-rw-r--r--Misc/NEWS.d/next/Core and Builtins/2023-12-07-12-00-04.gh-issue-74616.kgTGVb.rst2
-rw-r--r--Python/bltinmodule.c5
3 files changed, 42 insertions, 9 deletions
diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py
index 535856a..5587153 100644
--- a/Lib/test/test_builtin.py
+++ b/Lib/test/test_builtin.py
@@ -2269,7 +2269,10 @@ class PtyTests(unittest.TestCase):
return lines
- def check_input_tty(self, prompt, terminal_input, stdio_encoding=None):
+ def check_input_tty(self, prompt, terminal_input, stdio_encoding=None, *,
+ expected=None,
+ stdin_errors='surrogateescape',
+ stdout_errors='replace'):
if not sys.stdin.isatty() or not sys.stdout.isatty():
self.skipTest("stdin and stdout must be ttys")
def child(wpipe):
@@ -2277,22 +2280,26 @@ class PtyTests(unittest.TestCase):
if stdio_encoding:
sys.stdin = io.TextIOWrapper(sys.stdin.detach(),
encoding=stdio_encoding,
- errors='surrogateescape')
+ errors=stdin_errors)
sys.stdout = io.TextIOWrapper(sys.stdout.detach(),
encoding=stdio_encoding,
- errors='replace')
+ errors=stdout_errors)
print("tty =", sys.stdin.isatty() and sys.stdout.isatty(), file=wpipe)
- print(ascii(input(prompt)), file=wpipe)
+ try:
+ print(ascii(input(prompt)), file=wpipe)
+ except BaseException as e:
+ print(ascii(f'{e.__class__.__name__}: {e!s}'), file=wpipe)
lines = self.run_child(child, terminal_input + b"\r\n")
# Check we did exercise the GNU readline path
self.assertIn(lines[0], {'tty = True', 'tty = False'})
if lines[0] != 'tty = True':
self.skipTest("standard IO in should have been a tty")
input_result = eval(lines[1]) # ascii() -> eval() roundtrip
- if stdio_encoding:
- expected = terminal_input.decode(stdio_encoding, 'surrogateescape')
- else:
- expected = terminal_input.decode(sys.stdin.encoding) # what else?
+ if expected is None:
+ if stdio_encoding:
+ expected = terminal_input.decode(stdio_encoding, 'surrogateescape')
+ else:
+ expected = terminal_input.decode(sys.stdin.encoding) # what else?
self.assertEqual(input_result, expected)
def test_input_tty(self):
@@ -2313,13 +2320,32 @@ class PtyTests(unittest.TestCase):
def test_input_tty_non_ascii(self):
self.skip_if_readline()
# Check stdin/stdout encoding is used when invoking PyOS_Readline()
- self.check_input_tty("prompté", b"quux\xe9", "utf-8")
+ self.check_input_tty("prompté", b"quux\xc3\xa9", "utf-8")
def test_input_tty_non_ascii_unicode_errors(self):
self.skip_if_readline()
# Check stdin/stdout error handler is used when invoking PyOS_Readline()
self.check_input_tty("prompté", b"quux\xe9", "ascii")
+ def test_input_tty_null_in_prompt(self):
+ self.check_input_tty("prompt\0", b"",
+ expected='ValueError: input: prompt string cannot contain '
+ 'null characters')
+
+ def test_input_tty_nonencodable_prompt(self):
+ self.skip_if_readline()
+ self.check_input_tty("prompté", b"quux", "ascii", stdout_errors='strict',
+ expected="UnicodeEncodeError: 'ascii' codec can't encode "
+ "character '\\xe9' in position 6: ordinal not in "
+ "range(128)")
+
+ def test_input_tty_nondecodable_input(self):
+ self.skip_if_readline()
+ self.check_input_tty("prompt", b"quux\xe9", "ascii", stdin_errors='strict',
+ expected="UnicodeDecodeError: 'ascii' codec can't decode "
+ "byte 0xe9 in position 4: ordinal not in "
+ "range(128)")
+
def test_input_no_stdout_fileno(self):
# Issue #24402: If stdin is the original terminal but stdout.fileno()
# fails, do not use the original stdout file descriptor
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-12-07-12-00-04.gh-issue-74616.kgTGVb.rst b/Misc/NEWS.d/next/Core and Builtins/2023-12-07-12-00-04.gh-issue-74616.kgTGVb.rst
new file mode 100644
index 0000000..5c345be
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2023-12-07-12-00-04.gh-issue-74616.kgTGVb.rst
@@ -0,0 +1,2 @@
+:func:`input` now raises a ValueError when output on the terminal if the
+prompt contains embedded null characters instead of silently truncating it.
diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c
index 7a96251..960bca0 100644
--- a/Python/bltinmodule.c
+++ b/Python/bltinmodule.c
@@ -2262,6 +2262,11 @@ builtin_input_impl(PyObject *module, PyObject *prompt)
goto _readline_errors;
assert(PyBytes_Check(po));
promptstr = PyBytes_AS_STRING(po);
+ if ((Py_ssize_t)strlen(promptstr) != PyBytes_GET_SIZE(po)) {
+ PyErr_SetString(PyExc_ValueError,
+ "input: prompt string cannot contain null characters");
+ goto _readline_errors;
+ }
}
else {
po = NULL;