From: Victor Stinner Date: Wed, 15 Nov 2023 13:55:46 +0000 (+0100) Subject: [3.12] gh-111942: Fix SystemError in the TextIOWrapper constructor (GH-112061) (GH... X-Git-Tag: v3.12.1~124 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=1445d77282f9082f3fecde772ddf6bb2f5a383f1;p=thirdparty%2FPython%2Fcpython.git [3.12] gh-111942: Fix SystemError in the TextIOWrapper constructor (GH-112061) (GH-112089) In non-debug more the check for the "errors" argument is skipped, and then PyUnicode_AsUTF8() can fail, but its result was not checked. Co-authored-by: Victor Stinner (cherry picked from commit 9302f05f9af07332c414b3c19003efd1b1763cf3) Co-authored-by: Serhiy Storchaka --- diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py index 0f4a56001c0f..196b7d2b1429 100644 --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -2732,9 +2732,7 @@ class TextIOWrapperTest(unittest.TestCase): if support.Py_DEBUG or sys.flags.dev_mode or self.is_C: with self.assertRaises(UnicodeEncodeError): t.__init__(b, encoding="utf-8", errors='\udcfe') - if support.Py_DEBUG or sys.flags.dev_mode: - # TODO: If encoded to UTF-8, should also be checked for - # embedded null characters. + if support.Py_DEBUG or sys.flags.dev_mode or self.is_C: with self.assertRaises(ValueError): t.__init__(b, encoding="utf-8", errors='replace\0') with self.assertRaises(TypeError): diff --git a/Misc/NEWS.d/next/Library/2023-11-14-18-43-55.gh-issue-111942.x1pnrj.rst b/Misc/NEWS.d/next/Library/2023-11-14-18-43-55.gh-issue-111942.x1pnrj.rst new file mode 100644 index 000000000000..ca58a6fa5d6a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-11-14-18-43-55.gh-issue-111942.x1pnrj.rst @@ -0,0 +1,2 @@ +Fix SystemError in the TextIOWrapper constructor with non-encodable "errors" +argument in non-debug mode. diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c index d4797ca59ebe..efada7f04953 100644 --- a/Modules/_io/textio.c +++ b/Modules/_io/textio.c @@ -1119,6 +1119,15 @@ _io_TextIOWrapper___init___impl(textio *self, PyObject *buffer, else if (io_check_errors(errors)) { return -1; } + Py_ssize_t errors_len; + const char *errors_str = PyUnicode_AsUTF8AndSize(errors, &errors_len); + if (errors_str == NULL) { + return -1; + } + if (strlen(errors_str) != (size_t)errors_len) { + PyErr_SetString(PyExc_ValueError, "embedded null character"); + return -1; + } if (validate_newline(newline) < 0) { return -1; @@ -1191,11 +1200,11 @@ _io_TextIOWrapper___init___impl(textio *self, PyObject *buffer, /* Build the decoder object */ _PyIO_State *state = find_io_state_by_def(Py_TYPE(self)); self->state = state; - if (_textiowrapper_set_decoder(self, codec_info, PyUnicode_AsUTF8(errors)) != 0) + if (_textiowrapper_set_decoder(self, codec_info, errors_str) != 0) goto error; /* Build the encoder object */ - if (_textiowrapper_set_encoder(self, codec_info, PyUnicode_AsUTF8(errors)) != 0) + if (_textiowrapper_set_encoder(self, codec_info, errors_str) != 0) goto error; /* Finished sorting out the codec details */