From a0ceb731fb8bbd4aeefdb25b7aa9d5fa7abed5f9 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Thu, 6 Aug 2009 20:29:56 +0000 Subject: Merged revisions 74336 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ........ r74336 | antoine.pitrou | 2009-08-06 22:18:29 +0200 (jeu., 06 août 2009) | 8 lines Issue #6629: Fix a data corruption issue in the new `io` package, which could occur when writing to a BufferedRandom object (e.g. a file opened in "rb+" or "wb+" mode) after having buffered a certain amount of data for reading. This bug was not present in the pure Python implementation. Yes, this is a serious issue. ........ --- Lib/test/test_io.py | 20 ++++++++++++++++++++ Misc/NEWS | 5 +++++ Modules/_io/bufferedio.c | 13 +++++++++++++ 3 files changed, 38 insertions(+) diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py index 1f1cba2..a9094d9 100644 --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -1328,6 +1328,26 @@ class BufferedRandomTest(BufferedReaderTest, BufferedWriterTest): bufio.readinto(bytearray(1)) self.check_writes(_read) + def test_write_after_readahead(self): + # Issue #6629: writing after the buffer was filled by readahead should + # first rewind the raw stream. + for overwrite_size in [1, 5]: + raw = self.BytesIO(b"A" * 10) + bufio = self.tp(raw, 4) + # Trigger readahead + self.assertEqual(bufio.read(1), b"A") + self.assertEqual(bufio.tell(), 1) + # Overwriting should rewind the raw stream if it needs so + bufio.write(b"B" * overwrite_size) + self.assertEqual(bufio.tell(), overwrite_size + 1) + # If the write size was smaller than the buffer size, flush() and + # check that rewind happens. + bufio.flush() + self.assertEqual(bufio.tell(), overwrite_size + 1) + s = raw.getvalue() + self.assertEqual(s, + b"A" + b"B" * overwrite_size + b"A" * (9 - overwrite_size)) + def test_misbehaved_io(self): BufferedReaderTest.test_misbehaved_io(self) BufferedWriterTest.test_misbehaved_io(self) diff --git a/Misc/NEWS b/Misc/NEWS index bf70fc8..9ae93aa 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -63,6 +63,11 @@ C-API Library ------- +- Issue #6629: Fix a data corruption issue in the new I/O library, which could + occur when writing to a BufferedRandom object (e.g. a file opened in "rb+" or + "wb+" mode) after having buffered a certain amount of data for reading. This + bug was not present in the pure Python implementation. + - Issue #6622: Fix "local variable 'secret' referenced before assignment" bug in POP3.apop. diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c index 98f8413..d8b6471 100644 --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -1757,6 +1757,19 @@ bufferedwriter_write(buffered *self, PyObject *args) } Py_CLEAR(res); + /* Adjust the raw stream position if it is away from the logical stream + position. This happens if the read buffer has been filled but not + modified (and therefore _bufferedwriter_flush_unlocked() didn't rewind + the raw stream by itself). + Fixes issue #6629. + */ + n = RAW_OFFSET(self); + if (n != 0) { + if (_buffered_raw_seek(self, -n, 1) < 0) + goto error; + self->raw_pos -= n; + } + /* Then write buf itself. At this point the buffer has been emptied. */ remaining = buf.len; written = 0; -- cgit v0.12