https://github.com/python/cpython/commit/c98773633c97463e35eb51fac81d1095e8061fe0
commit: c98773633c97463e35eb51fac81d1095e8061fe0
branch: main
author: Thomas Kowalski <[email protected]>
committer: vstinner <[email protected]>
date: 2026-06-01T13:01:57Z
summary:
gh-149046: fix: correctly handle `str` subclasses in `io.StringIO` (#149047)
files:
A Misc/NEWS.d/next/Library/2026-04-27-11-12-00.gh-issue-149046.74shDd.rst
M Lib/test/test_io/test_memoryio.py
M Modules/_io/stringio.c
diff --git a/Lib/test/test_io/test_memoryio.py
b/Lib/test/test_io/test_memoryio.py
index 482b183da23ffa2..3669ac0b038b71b 100644
--- a/Lib/test/test_io/test_memoryio.py
+++ b/Lib/test/test_io/test_memoryio.py
@@ -967,6 +967,25 @@ def test_setstate(self):
memio.close()
self.assertRaises(ValueError, memio.__setstate__, ("closed", "", 0,
None))
+ def test_write_str_subclass(self):
+ # Writing a str subclass should use the subclass's unicode data
+ # directly, not call __str__ on it (which may return a different
+ # value). gh-149047
+ class MyStr(str):
+ def __str__(self):
+ return "WRONG"
+
+ s = MyStr("correct")
+ memio = self.ioclass()
+ memio.write(s)
+ self.assertEqual(memio.getvalue(), "correct")
+
+ # Also test the fast path where pos == string_size (STATE_ACCUMULATING)
+ memio2 = self.ioclass()
+ memio2.write(MyStr("hello "))
+ memio2.write(MyStr("world"))
+ self.assertEqual(memio2.getvalue(), "hello world")
+
class CStringIOPickleTest(PyStringIOPickleTest):
UnsupportedOperation = io.UnsupportedOperation
diff --git
a/Misc/NEWS.d/next/Library/2026-04-27-11-12-00.gh-issue-149046.74shDd.rst
b/Misc/NEWS.d/next/Library/2026-04-27-11-12-00.gh-issue-149046.74shDd.rst
new file mode 100644
index 000000000000000..b05c4222e30fcd2
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-04-27-11-12-00.gh-issue-149046.74shDd.rst
@@ -0,0 +1,2 @@
+:mod:`io`: Fix :class:`io.StringIO` serialization: no longer call ``str(obj)``
on :class:`str`
+subclasses. Patch by Thomas Kowalski.
diff --git a/Modules/_io/stringio.c b/Modules/_io/stringio.c
index 0d9196f3647dde8..b8601383ad0a26f 100644
--- a/Modules/_io/stringio.c
+++ b/Modules/_io/stringio.c
@@ -225,7 +225,9 @@ write_str(stringio *self, PyObject *obj)
if (self->state == STATE_ACCUMULATING) {
if (self->string_size == self->pos) {
- if (PyUnicodeWriter_WriteStr(self->writer, decoded))
+ // gh-149046: Avoid PyUnicodeWriter_WriteStr() which calls str(obj)
+ // on str subclasses
+ if (_PyUnicodeWriter_WriteStr((_PyUnicodeWriter*)self->writer,
decoded))
goto fail;
goto success;
}
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]