https://github.com/python/cpython/commit/8c282627bd8e9cf007fedd8438bd7883500a8495 commit: 8c282627bd8e9cf007fedd8438bd7883500a8495 branch: 3.15 author: Miss Islington (bot) <[email protected]> committer: JelleZijlstra <[email protected]> date: 2026-10-22T19:29:58Z summary:
[3.15] gh-159739: Respect readline limits after a short read (GH-159974) (#160246) Backport to 3.15 and 3.14. Both branches use a bytearray instead of PyBytesWriter; the test lives in Lib/test/test_io.py on 3.14. (cherry picked from commit 87eaef117191037cebce2becea5350ff4f45dee3) Co-authored-by: Jelle Zijlstra <[email protected]> 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/test_general.py M Modules/_io/iobase.c diff --git a/Lib/_pyio.py b/Lib/_pyio.py index 342a50724d49fb..b351c35e4bbea5 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/test_general.py b/Lib/test/test_io/test_general.py index 085ed3ea6a95ee..d12c5535b263ef 100644 --- a/Lib/test/test_io/test_general.py +++ b/Lib/test/test_io/test_general.py @@ -319,6 +319,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 1253f124108bdb..b57ceb88569414 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]
