From f3a61de07ff3654eed9c1722bc9a728320b3f17a Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Mon, 6 Mar 2017 15:30:48 +0200 Subject: [PATCH 1/2] bpo-8256: Fixed possible failing or crashing input() if attributes "encoding" or "errors" of sys.stdin or sys.stdout are not set or are not strings. --- Misc/NEWS | 3 +++ Python/bltinmodule.c | 14 ++++++++++---- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS index 81b02fdd4a48b3..cdfcea10ccb055 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -266,6 +266,9 @@ Extension Modules Library ------- +- bpo-8256: Fixed possible failing or crashing input() if attributes "encoding" + or "errors" of sys.stdin or sys.stdout are not set or are not strings. + - bpo-29623: Allow use of path-like object as a single argument in ConfigParser.read(). Patch by David Ellis. diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 63f19986760088..e74f911ed1754b 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -1928,10 +1928,12 @@ builtin_input_impl(PyObject *module, PyObject *prompt) stdin_encoding = _PyObject_GetAttrId(fin, &PyId_encoding); stdin_errors = _PyObject_GetAttrId(fin, &PyId_errors); - if (!stdin_encoding || !stdin_errors) + if (!stdin_encoding || !stdin_errors || + !PyUnicode_Check(stdin_encoding) || + !PyUnicode_Check(stdin_errors)) /* stdin is a text stream, so it must have an encoding. */ - goto _readline_errors; + goto fallback; stdin_encoding_str = PyUnicode_AsUTF8(stdin_encoding); stdin_errors_str = PyUnicode_AsUTF8(stdin_errors); if (!stdin_encoding_str || !stdin_errors_str) @@ -1947,8 +1949,10 @@ builtin_input_impl(PyObject *module, PyObject *prompt) PyObject *stringpo; stdout_encoding = _PyObject_GetAttrId(fout, &PyId_encoding); stdout_errors = _PyObject_GetAttrId(fout, &PyId_errors); - if (!stdout_encoding || !stdout_errors) - goto _readline_errors; + if (!stdout_encoding || !stdout_errors || + !PyUnicode_Check(stdout_encoding) || + !PyUnicode_Check(stdout_errors)) + goto fallback; stdout_encoding_str = PyUnicode_AsUTF8(stdout_encoding); stdout_errors_str = PyUnicode_AsUTF8(stdout_errors); if (!stdout_encoding_str || !stdout_errors_str) @@ -2011,7 +2015,9 @@ builtin_input_impl(PyObject *module, PyObject *prompt) return NULL; } +fallback: /* Fallback if we're not interactive */ + PyErr_Clear(); if (prompt != NULL) { if (PyFile_WriteObject(prompt, fout, Py_PRINT_RAW) != 0) return NULL; From d2669f4e3cb3d5a7c39cbf98c33213ab566d65b0 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Tue, 7 Mar 2017 10:52:25 +0200 Subject: [PATCH 2/2] Fix refleaks and clean a code. --- Python/bltinmodule.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index e74f911ed1754b..29b24da3f813ae 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -1926,14 +1926,15 @@ builtin_input_impl(PyObject *module, PyObject *prompt) PyObject *result; size_t len; + /* stdin is a text stream, so it must have an encoding. */ stdin_encoding = _PyObject_GetAttrId(fin, &PyId_encoding); stdin_errors = _PyObject_GetAttrId(fin, &PyId_errors); if (!stdin_encoding || !stdin_errors || - !PyUnicode_Check(stdin_encoding) || - !PyUnicode_Check(stdin_errors)) - /* stdin is a text stream, so it must have an - encoding. */ - goto fallback; + !PyUnicode_Check(stdin_encoding) || + !PyUnicode_Check(stdin_errors)) { + tty = 0; + goto _readline_errors; + } stdin_encoding_str = PyUnicode_AsUTF8(stdin_encoding); stdin_errors_str = PyUnicode_AsUTF8(stdin_errors); if (!stdin_encoding_str || !stdin_errors_str) @@ -1950,9 +1951,11 @@ builtin_input_impl(PyObject *module, PyObject *prompt) stdout_encoding = _PyObject_GetAttrId(fout, &PyId_encoding); stdout_errors = _PyObject_GetAttrId(fout, &PyId_errors); if (!stdout_encoding || !stdout_errors || - !PyUnicode_Check(stdout_encoding) || - !PyUnicode_Check(stdout_errors)) - goto fallback; + !PyUnicode_Check(stdout_encoding) || + !PyUnicode_Check(stdout_errors)) { + tty = 0; + goto _readline_errors; + } stdout_encoding_str = PyUnicode_AsUTF8(stdout_encoding); stdout_errors_str = PyUnicode_AsUTF8(stdout_errors); if (!stdout_encoding_str || !stdout_errors_str) @@ -2006,18 +2009,20 @@ builtin_input_impl(PyObject *module, PyObject *prompt) Py_XDECREF(po); PyMem_FREE(s); return result; + _readline_errors: Py_XDECREF(stdin_encoding); Py_XDECREF(stdout_encoding); Py_XDECREF(stdin_errors); Py_XDECREF(stdout_errors); Py_XDECREF(po); - return NULL; + if (tty) + return NULL; + + PyErr_Clear(); } -fallback: /* Fallback if we're not interactive */ - PyErr_Clear(); if (prompt != NULL) { if (PyFile_WriteObject(prompt, fout, Py_PRINT_RAW) != 0) return NULL;