Skip to content

Commit 5721af0

Browse files
committed
gh-159739: Validate newline replacement in TextIOWrapper.write
A str subclass can override replace() and return a non-string while TextIOWrapper.write() translates newlines. The C implementation then treats the result as Unicode and can crash. Reject an invalid replacement with TypeError. Backport to 3.15 and 3.14; on 3.14, put the regression test in Lib/test/test_io.py.
1 parent d4750a7 commit 5721af0

3 files changed

Lines changed: 16 additions & 0 deletions

File tree

‎Lib/test/test_io/test_textio.py‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1448,6 +1448,15 @@ def _to_memoryview(buf):
14481448
class CTextIOWrapperTest(TextIOWrapperTest, CTestCase):
14491449
shutdown_error = "LookupError: unknown encoding: ascii"
14501450

1451+
def test_write_newline_replace_returns_non_string(self):
1452+
class Text(str):
1453+
def replace(self, *args):
1454+
return None
1455+
1456+
with self.TextIOWrapper(self.BytesIO(), newline='\r\n') as stream:
1457+
with self.assertRaisesRegex(TypeError, 'replace.*str'):
1458+
stream.write(Text('a\n'))
1459+
14511460
def test_chunk_size(self):
14521461
t = self.TextIOWrapper(self.BytesIO(), encoding="utf-8")
14531462
self.assertGreater(t._CHUNK_SIZE, 0)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Raise :exc:`TypeError` if a string subclass returns a non-string during newline translation in :class:`io.TextIOWrapper`.

‎Modules/_io/textio.c‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1768,6 +1768,12 @@ _io_TextIOWrapper_write_impl(textio *self, PyObject *text)
17681768
Py_DECREF(text);
17691769
if (newtext == NULL)
17701770
return NULL;
1771+
if (!PyUnicode_Check(newtext)) {
1772+
PyErr_Format(PyExc_TypeError,
1773+
"replace() should return a str, not %T", newtext);
1774+
Py_DECREF(newtext);
1775+
return NULL;
1776+
}
17711777
text = newtext;
17721778
}
17731779

0 commit comments

Comments
 (0)