]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.12] gh-111942: Fix SystemError in the TextIOWrapper constructor (GH-112061) (GH...
authorVictor Stinner <vstinner@python.org>
Wed, 15 Nov 2023 13:55:46 +0000 (14:55 +0100)
committerGitHub <noreply@github.com>
Wed, 15 Nov 2023 13:55:46 +0000 (15:55 +0200)
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 <vstinner@python.org>
(cherry picked from commit 9302f05f9af07332c414b3c19003efd1b1763cf3)

Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
Lib/test/test_io.py
Misc/NEWS.d/next/Library/2023-11-14-18-43-55.gh-issue-111942.x1pnrj.rst [new file with mode: 0644]
Modules/_io/textio.c

index 0f4a56001c0f379b653a9a68ab76e25654a84cf4..196b7d2b1429ab9ce53afb2ec3054594d0284731 100644 (file)
@@ -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 (file)
index 0000000..ca58a6f
--- /dev/null
@@ -0,0 +1,2 @@
+Fix SystemError in the TextIOWrapper constructor with non-encodable "errors"
+argument in non-debug mode.
index d4797ca59ebea237e457d99c3c74d42aa3ccf49d..efada7f0495357ae0cbbccfd1606f952b3302ed3 100644 (file)
@@ -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 */