https://github.com/python/cpython/commit/7b727ab601347a83e0a173a708aaa7018c9158aa
commit: 7b727ab601347a83e0a173a708aaa7018c9158aa
branch: main
author: Cody Maloney <[email protected]>
committer: StanFromIreland <[email protected]>
date: 2026-10-29T13:54:46Z
summary:

gh-160781: Fix `BytesIO` overflow handling for large sizes (#160783)

files:
A Misc/NEWS.d/next/Library/2026-10-27-15-26-53.gh-issue-160781.4VSeQK.rst
A Misc/NEWS.d/next/Library/2026-10-27-15-42-16.gh-issue-160781.VGLB9S.rst
M Lib/test/test_io/test_memoryio.py
M Modules/_io/bytesio.c

diff --git a/Lib/test/test_io/test_memoryio.py 
b/Lib/test/test_io/test_memoryio.py
index 349c7281230eeb..48337ae9e80a53 100644
--- a/Lib/test/test_io/test_memoryio.py
+++ b/Lib/test/test_io/test_memoryio.py
@@ -591,6 +591,10 @@ def test_issue141311(self):
         self.assertEqual(sys.maxsize, memio.seek(sys.maxsize))
         buf = bytearray(2)
         self.assertEqual(0, memio.readinto(buf))
+        # Writing there must not overflow the buffer size.
+        memio.seek(sys.maxsize - 1)
+        self.assertRaises((MemoryError, OverflowError), memio.write, b"x")
+        self.assertEqual(memio.getvalue(), b"")
 
     def test_peek(self):
         buf = self.buftype("1234567890")
@@ -984,6 +988,12 @@ def __index__(self):
             finally:
                 size.result.release()
 
+        # Sizes above 2**31 - 1 must work where C long is 32-bit.
+        if sys.maxsize > 2**31:
+            stream = self.ioclass(b'abc')
+            self.assertEqual(stream.truncate(2**31), 2**31)
+            self.assertEqual(stream.getvalue(), b'abc')
+
     def test_readinto_overlapping_buffer(self):
         with self.ioclass(b'abcd') as stream:
             with stream.getbuffer()[1:] as target:
diff --git 
a/Misc/NEWS.d/next/Library/2026-10-27-15-26-53.gh-issue-160781.4VSeQK.rst 
b/Misc/NEWS.d/next/Library/2026-10-27-15-26-53.gh-issue-160781.4VSeQK.rst
new file mode 100644
index 00000000000000..f6463a5d531369
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-10-27-15-26-53.gh-issue-160781.4VSeQK.rst
@@ -0,0 +1,3 @@
+Fix :class:`io.BytesIO` raising :exc:`SystemError` instead of
+:exc:`OverflowError` when writing at a position close to
+:data:`sys.maxsize`.
diff --git 
a/Misc/NEWS.d/next/Library/2026-10-27-15-42-16.gh-issue-160781.VGLB9S.rst 
b/Misc/NEWS.d/next/Library/2026-10-27-15-42-16.gh-issue-160781.VGLB9S.rst
new file mode 100644
index 00000000000000..73c8c177fc8828
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-10-27-15-42-16.gh-issue-160781.VGLB9S.rst
@@ -0,0 +1,2 @@
+Fix :class:`io.BytesIO` implementation of :meth:`io.IOBase.truncate` rejecting
+sizes larger than ``2**31 - 1`` on Windows.
diff --git a/Modules/_io/bytesio.c b/Modules/_io/bytesio.c
index 01f63f8a677d37..2571da4538363f 100644
--- a/Modules/_io/bytesio.c
+++ b/Modules/_io/bytesio.c
@@ -221,6 +221,9 @@ resize_buffer_lock_held(bytesio *self, size_t size)
         /* Major upsize; resize up to exact size */
         alloc = size + 1;
     }
+    if (alloc > PY_SSIZE_T_MAX) {
+        goto overflow;
+    }
 
     if (SHARED_BUF(self)) {
         if (unshare_buffer_lock_held(self, alloc) < 0)
@@ -755,7 +758,7 @@ _io_BytesIO_truncate_impl(bytesio *self, PyObject *size)
         new_size = self->pos;
     }
     else {
-        new_size = PyLong_AsLong(size);
+        new_size = PyNumber_AsSsize_t(size, PyExc_OverflowError);
         if (new_size == -1 && PyErr_Occurred()) {
             return NULL;
         }

_______________________________________________
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]

Reply via email to