summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Lib/test/test_io.py4
-rw-r--r--Misc/NEWS.d/next/Library/2023-11-14-18-43-55.gh-issue-111942.x1pnrj.rst2
-rw-r--r--Modules/_io/textio.c13
3 files changed, 14 insertions, 5 deletions
diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py
index 0f4a560..196b7d2 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 0000000..ca58a6f
--- /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 d4797ca..efada7f 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 */