Merged revisions 74336 via svnmerge from

svn+ssh://pythondev@svn.python.org/python/trunk

........
  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.
........
This commit is contained in:
Antoine Pitrou 2009-08-06 20:29:56 +00:00
parent 5a5453978f
commit a0ceb731fb
3 changed files with 38 additions and 0 deletions

View File

@ -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)

View File

@ -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.

View File

@ -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;