Skip to content

Commit 52cafc8

Browse files
[3.12] pythongh-111942: Fix SystemError in the TextIOWrapper constructor (pythonGH-112061) (pythonGH-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 <[email protected]> (cherry picked from commit 9302f05) Co-authored-by: Serhiy Storchaka <[email protected]>
1 parent c4fc137 commit 52cafc8

File tree

3 files changed

+14
-5
lines changed

3 files changed

+14
-5
lines changed

Lib/test/test_io.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2629,9 +2629,7 @@ def test_constructor(self):
26292629
if support.Py_DEBUG or sys.flags.dev_mode or self.is_C:
26302630
with self.assertRaises(UnicodeEncodeError):
26312631
t.__init__(b, encoding="utf-8", errors='\udcfe')
2632-
if support.Py_DEBUG or sys.flags.dev_mode:
2633-
# TODO: If encoded to UTF-8, should also be checked for
2634-
# embedded null characters.
2632+
if support.Py_DEBUG or sys.flags.dev_mode or self.is_C:
26352633
with self.assertRaises(ValueError):
26362634
t.__init__(b, encoding="utf-8", errors='replace\0')
26372635
with self.assertRaises(TypeError):
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix SystemError in the TextIOWrapper constructor with non-encodable "errors"
2+
argument in non-debug mode.

Modules/_io/textio.c

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1099,6 +1099,15 @@ _io_TextIOWrapper___init___impl(textio *self, PyObject *buffer,
10991099
else if (io_check_errors(errors)) {
11001100
return -1;
11011101
}
1102+
Py_ssize_t errors_len;
1103+
const char *errors_str = PyUnicode_AsUTF8AndSize(errors, &errors_len);
1104+
if (errors_str == NULL) {
1105+
return -1;
1106+
}
1107+
if (strlen(errors_str) != (size_t)errors_len) {
1108+
PyErr_SetString(PyExc_ValueError, "embedded null character");
1109+
return -1;
1110+
}
11021111

11031112
if (validate_newline(newline) < 0) {
11041113
return -1;
@@ -1171,11 +1180,11 @@ _io_TextIOWrapper___init___impl(textio *self, PyObject *buffer,
11711180
Py_INCREF(buffer);
11721181

11731182
/* Build the decoder object */
1174-
if (_textiowrapper_set_decoder(self, codec_info, PyUnicode_AsUTF8(errors)) != 0)
1183+
if (_textiowrapper_set_decoder(self, codec_info, errors_str) != 0)
11751184
goto error;
11761185

11771186
/* Build the encoder object */
1178-
if (_textiowrapper_set_encoder(self, codec_info, PyUnicode_AsUTF8(errors)) != 0)
1187+
if (_textiowrapper_set_encoder(self, codec_info, errors_str) != 0)
11791188
goto error;
11801189

11811190
/* Finished sorting out the codec details */

0 commit comments

Comments
 (0)