From 3b82bfb721bfee366b1ececa68a19c469b530c6b Mon Sep 17 00:00:00 2001 From: Cody Maloney Date: Thu, 29 Oct 2026 06:52:42 -0700 Subject: [PATCH] [3.15] gh-160781: Fix `StringIO.truncate()` rejecting sizes above `2**31 - 1` on Windows (GH-160784) (cherry picked from commit 0bfee223909adc113ece862cb8d7d807c35e201c) Co-authored-by: Cody Maloney --- Lib/test/test_io/test_memoryio.py | 7 +++++++ .../Library/2026-10-27-15-27-32.gh-issue-160781.kARuHu.rst | 2 ++ Modules/_io/stringio.c | 2 +- 3 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Library/2026-10-27-15-27-32.gh-issue-160781.kARuHu.rst diff --git a/Lib/test/test_io/test_memoryio.py b/Lib/test/test_io/test_memoryio.py index c82acceffb09c8b..f70a589f45d47a9 100644 --- a/Lib/test/test_io/test_memoryio.py +++ b/Lib/test/test_io/test_memoryio.py @@ -1004,6 +1004,13 @@ class CStringIOTest(PyStringIOTest): ioclass = io.StringIO UnsupportedOperation = io.UnsupportedOperation + def test_truncate_large_size(self): + # Sizes above 2**31 - 1 must work where C long is 32-bit. + if sys.maxsize > 2**31: + stream = self.ioclass("abc") + self.assertEqual(stream.truncate(2**31), 2**31) + self.assertEqual(stream.getvalue(), "abc") + # XXX: For the Python version of io.StringIO, this is highly # dependent on the encoding used for the underlying buffer. def test_widechar(self): diff --git a/Misc/NEWS.d/next/Library/2026-10-27-15-27-32.gh-issue-160781.kARuHu.rst b/Misc/NEWS.d/next/Library/2026-10-27-15-27-32.gh-issue-160781.kARuHu.rst new file mode 100644 index 000000000000000..1f1e25d8b461b4e --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-10-27-15-27-32.gh-issue-160781.kARuHu.rst @@ -0,0 +1,2 @@ +Fix :class:`io.StringIO` implementation of :meth:`io.IOBase.truncate` +rejecting sizes larger than ``2**31 - 1`` on Windows. diff --git a/Modules/_io/stringio.c b/Modules/_io/stringio.c index b8601383ad0a26f..08a3f7e16e4d8a3 100644 --- a/Modules/_io/stringio.c +++ b/Modules/_io/stringio.c @@ -469,7 +469,7 @@ _io_StringIO_truncate_impl(stringio *self, PyObject *pos) size = self->pos; } else { - size = PyLong_AsLong(pos); + size = PyNumber_AsSsize_t(pos, PyExc_OverflowError); if (size == -1 && PyErr_Occurred()) { return NULL; }