bpo-40638: Check for attribute lookup failure in builtin_input_impl

Add tests to cover this case.
This commit is contained in:
Maxwell Bernstein 2020-05-15 15:12:15 -07:00
parent 62d618c06b
commit 400bef9ca6
2 changed files with 37 additions and 7 deletions

View File

@ -75,6 +75,23 @@ class BitBucket:
def write(self, line):
pass
class MalformedInputStream:
def readline(self):
return "foobar\n"
def fileno(self):
return 0
class MalformedOutputStream:
def __init__(self):
self.value = ""
def fileno(self):
return 1
def write(self, value):
self.value += value
test_conv_no_sign = [
('0', 0),
('1', 1),
@ -1302,6 +1319,13 @@ class BuiltinTest(unittest.TestCase):
sys.stdin = io.StringIO()
self.assertRaises(EOFError, input)
# input() in tty mode with a malformed input stream should attempt
# to call .readline()
sys.stdin = MalformedInputStream()
sys.stdout = MalformedOutputStream()
self.assertEqual(input("baz"), "foobar") # strips \n
self.assertEqual(sys.stdout.value, "baz")
del sys.stdout
self.assertRaises(RuntimeError, input, 'prompt')
del sys.stdin

View File

@ -2010,17 +2010,21 @@ builtin_input_impl(PyObject *module, PyObject *prompt)
/* stdin is a text stream, so it must have an encoding. */
stdin_encoding = _PyObject_GetAttrId(fin, &PyId_encoding);
if (!stdin_encoding || !PyUnicode_Check(stdin_encoding)) {
goto _readline_disable_tty_and_fall_back;
}
stdin_errors = _PyObject_GetAttrId(fin, &PyId_errors);
if (!stdin_encoding || !stdin_errors ||
!PyUnicode_Check(stdin_encoding) ||
!PyUnicode_Check(stdin_errors)) {
tty = 0;
goto _readline_errors;
if (!stdin_errors || !PyUnicode_Check(stdin_errors)) {
goto _readline_disable_tty_and_fall_back;
}
stdin_encoding_str = PyUnicode_AsUTF8(stdin_encoding);
stdin_errors_str = PyUnicode_AsUTF8(stdin_errors);
if (!stdin_encoding_str || !stdin_errors_str)
if (!stdin_encoding_str) {
goto _readline_errors;
}
stdin_errors_str = PyUnicode_AsUTF8(stdin_errors);
if (!stdin_errors_str) {
goto _readline_errors;
}
tmp = _PyObject_CallMethodIdNoArgs(fout, &PyId_flush);
if (tmp == NULL)
PyErr_Clear();
@ -2099,6 +2103,8 @@ builtin_input_impl(PyObject *module, PyObject *prompt)
return result;
_readline_disable_tty_and_fall_back:
tty = 0;
_readline_errors:
Py_XDECREF(stdin_encoding);
Py_XDECREF(stdout_encoding);