]> granicus.if.org Git - python/commitdiff
bpo-31271: Fix an assertion failure in io.TextIOWrapper.write. (#3201)
authorOren Milman <orenmn@gmail.com>
Fri, 25 Aug 2017 18:14:54 +0000 (21:14 +0300)
committerSerhiy Storchaka <storchaka@gmail.com>
Fri, 25 Aug 2017 18:14:54 +0000 (21:14 +0300)
Lib/test/test_io.py
Misc/NEWS.d/next/Core and Builtins/2017-08-25-20-43-22.bpo-31271.YMduKF.rst [new file with mode: 0644]
Modules/_io/textio.c

index ab0cbe163613ecdd23c4b68b7c42684686696a94..ba95c1442fa49dd0d85b1c309f66e7f6b21bddd6 100644 (file)
@@ -3225,6 +3225,14 @@ class TextIOWrapperTest(unittest.TestCase):
         t = self.TextIOWrapper(self.StringIO('a'))
         self.assertRaises(TypeError, t.read)
 
+    def test_illegal_encoder(self):
+        # Issue 31271: Calling write() while the return value of encoder's
+        # encode() is invalid shouldn't cause an assertion failure.
+        rot13 = codecs.lookup("rot13")
+        with support.swap_attr(rot13, '_is_text_encoding', True):
+            t = io.TextIOWrapper(io.BytesIO(b'foo'), encoding="rot13")
+        self.assertRaises(TypeError, t.write, 'bar')
+
     def test_illegal_decoder(self):
         # Issue #17106
         # Bypass the early encoding check added in issue 20404
diff --git a/Misc/NEWS.d/next/Core and Builtins/2017-08-25-20-43-22.bpo-31271.YMduKF.rst b/Misc/NEWS.d/next/Core and Builtins/2017-08-25-20-43-22.bpo-31271.YMduKF.rst
new file mode 100644 (file)
index 0000000..7bb7880
--- /dev/null
@@ -0,0 +1,2 @@
+Fix an assertion failure in the write() method of `io.TextIOWrapper`, when
+the encoder doesn't return a bytes object. Patch by Oren Milman.
index 5103ae659ce7de8e987c1544f4d797ff604fad73..402f743c61f58690b7208db058f31b369176389a 100644 (file)
@@ -1387,6 +1387,13 @@ _io_TextIOWrapper_write_impl(textio *self, PyObject *text)
     Py_DECREF(text);
     if (b == NULL)
         return NULL;
+    if (!PyBytes_Check(b)) {
+        PyErr_Format(PyExc_TypeError,
+                     "encoder should return a bytes object, not '%.200s'",
+                     Py_TYPE(b)->tp_name);
+        Py_DECREF(b);
+        return NULL;
+    }
 
     if (self->pending_bytes == NULL) {
         self->pending_bytes = PyList_New(0);