https://github.com/python/cpython/commit/105c6419fec67478d6400583932a042e4cda1426
commit: 105c6419fec67478d6400583932a042e4cda1426
branch: 3.14
author: Jelle Zijlstra <[email protected]>
committer: JelleZijlstra <[email protected]>
date: 2026-10-24T13:42:51-07:00
summary:

[3.14] gh-159739: Respect readline limits after a short read (GH-159974) 
(#160483)


(cherry picked from commit 87eaef117191037cebce2becea5350ff4f45dee3)

files:
A Misc/NEWS.d/next/Library/2026-10-20-00-00-00.gh-issue-159739.4c9783.rst
M Lib/_pyio.py
M Lib/test/test_io.py
M Modules/_io/iobase.c

diff --git a/Lib/_pyio.py b/Lib/_pyio.py
index cc336d2939443c..01fd821fb0049c 100644
--- a/Lib/_pyio.py
+++ b/Lib/_pyio.py
@@ -528,7 +528,7 @@ def nreadahead():
                     return 1
                 n = (readahead.find(b"\n") + 1) or len(readahead)
                 if size >= 0:
-                    n = min(n, size)
+                    n = min(n, size - len(res))
                 return n
         else:
             def nreadahead():
diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py
index d11e66e94b4970..cbec18fb403632 100644
--- a/Lib/test/test_io.py
+++ b/Lib/test/test_io.py
@@ -624,6 +624,22 @@ def test_readline(self):
         with self.open(os_helper.TESTFN, "r", encoding="utf-8") as f:
             self.assertRaises(TypeError, f.readline, 5.3)
 
+    def test_readline_limit_with_short_read(self):
+        class Reader(self.IOBase):
+            data = b"abcdef"
+
+            def peek(self, size):
+                return self.data
+
+            def read(self, size):
+                data = self.data[:min(size, 2)]
+                self.data = self.data[len(data):]
+                return data
+
+        reader = Reader()
+        self.assertEqual(reader.readline(3), b"abc")
+        self.assertEqual(reader.data, b"def")
+
     def test_readline_nonsizeable(self):
         # Issue #30061
         # Crash when readline() returns an object without __len__
diff --git 
a/Misc/NEWS.d/next/Library/2026-10-20-00-00-00.gh-issue-159739.4c9783.rst 
b/Misc/NEWS.d/next/Library/2026-10-20-00-00-00.gh-issue-159739.4c9783.rst
new file mode 100644
index 00000000000000..b65ac4cede106b
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-10-20-00-00-00.gh-issue-159739.4c9783.rst
@@ -0,0 +1,2 @@
+Fix :meth:`io.IOBase.readline` returning more bytes than requested when a
+stream supports :meth:`!peek` and returns short reads.
diff --git a/Modules/_io/iobase.c b/Modules/_io/iobase.c
index e291d7cfc4710f..5cbd28ca136b4b 100644
--- a/Modules/_io/iobase.c
+++ b/Modules/_io/iobase.c
@@ -609,8 +609,9 @@ _io__IOBase_readline_impl(PyObject *self, Py_ssize_t limit)
                 Py_ssize_t n = 0;
                 const char *buf = PyBytes_AS_STRING(readahead);
                 if (limit >= 0) {
+                    Py_ssize_t remaining = limit - 
PyByteArray_GET_SIZE(buffer);
                     do {
-                        if (n >= PyBytes_GET_SIZE(readahead) || n >= limit)
+                        if (n >= PyBytes_GET_SIZE(readahead) || n >= remaining)
                             break;
                         if (buf[n++] == '\n')
                             break;

_______________________________________________
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