]> granicus.if.org Git - python/commitdiff
[3.6] bpo-31271: Fix an assertion failure in io.TextIOWrapper.write. (GH-3201) (...
authorOren Milman <orenmn@gmail.com>
Sat, 26 Aug 2017 17:29:40 +0000 (20:29 +0300)
committerSerhiy Storchaka <storchaka@gmail.com>
Sat, 26 Aug 2017 17:29:40 +0000 (20:29 +0300)
(cherry picked from commit a5b4ea15b61e3f3985f4f0748a18f8b888a63532)

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 6a2c7a9fca4fadabc710feef6129e8e683f525de..7057c927c3f5ee436f05f1a4196b4ab1c40b8e87 100644 (file)
@@ -3163,6 +3163,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 61adcf60508e2fde246d550e9eaed7fd01468f96..801bb1745bbccc6afc625571dada08ee9078dca4 100644 (file)
@@ -1331,6 +1331,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);