Skip to content

Commit 7f58ab2

Browse files
gh-111942: Fix SystemError in the TextIOWrapper constructor (#112061)
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)
1 parent 24216d0 commit 7f58ab2

File tree

3 files changed

+9
-5
lines changed

3 files changed

+9
-5
lines changed

Lib/test/test_io.py

+1-3
Original file line numberDiff line numberDiff line change
@@ -2732,9 +2732,7 @@ def test_constructor(self):
27322732
if support.Py_DEBUG or sys.flags.dev_mode or self.is_C:
27332733
with self.assertRaises(UnicodeEncodeError):
27342734
t.__init__(b, encoding="utf-8", errors='\udcfe')
2735-
if support.Py_DEBUG or sys.flags.dev_mode:
2736-
# TODO: If encoded to UTF-8, should also be checked for
2737-
# embedded null characters.
2735+
if support.Py_DEBUG or sys.flags.dev_mode or self.is_C:
27382736
with self.assertRaises(ValueError):
27392737
t.__init__(b, encoding="utf-8", errors='replace\0')
27402738
with self.assertRaises(TypeError):
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

+6-2
Original file line numberDiff line numberDiff line change
@@ -1119,6 +1119,10 @@ _io_TextIOWrapper___init___impl(textio *self, PyObject *buffer,
11191119
else if (io_check_errors(errors)) {
11201120
return -1;
11211121
}
1122+
const char *errors_str = _PyUnicode_AsUTF8NoNUL(errors);
1123+
if (errors_str == NULL) {
1124+
return -1;
1125+
}
11221126

11231127
if (validate_newline(newline) < 0) {
11241128
return -1;
@@ -1191,11 +1195,11 @@ _io_TextIOWrapper___init___impl(textio *self, PyObject *buffer,
11911195
/* Build the decoder object */
11921196
_PyIO_State *state = find_io_state_by_def(Py_TYPE(self));
11931197
self->state = state;
1194-
if (_textiowrapper_set_decoder(self, codec_info, PyUnicode_AsUTF8(errors)) != 0)
1198+
if (_textiowrapper_set_decoder(self, codec_info, errors_str) != 0)
11951199
goto error;
11961200

11971201
/* Build the encoder object */
1198-
if (_textiowrapper_set_encoder(self, codec_info, PyUnicode_AsUTF8(errors)) != 0)
1202+
if (_textiowrapper_set_encoder(self, codec_info, errors_str) != 0)
11991203
goto error;
12001204

12011205
/* Finished sorting out the codec details */

0 commit comments

Comments
 (0)