]> granicus.if.org Git - python/commitdiff
Issue #12062: In the `io` module, fix a flushing bug when doing a certain
authorAntoine Pitrou <solipsis@pitrou.net>
Thu, 12 May 2011 22:31:52 +0000 (00:31 +0200)
committerAntoine Pitrou <solipsis@pitrou.net>
Thu, 12 May 2011 22:31:52 +0000 (00:31 +0200)
type of I/O sequence on a file opened in read+write mode (namely: reading,
seeking a bit forward, writing, then seeking before the previous write but
still within buffered data, and writing again).

Lib/test/test_io.py
Misc/NEWS
Modules/_io/bufferedio.c

index 0bad56debac33a28543be3a5ef49876bc9b2e442..8af8a6462247e96f3cffb2f3685aae61f088663b 100644 (file)
@@ -1462,6 +1462,32 @@ class BufferedRandomTest(BufferedReaderTest, BufferedWriterTest):
             self.assertEqual(s,
                 b"A" + b"B" * overwrite_size + b"A" * (9 - overwrite_size))
 
+    def test_write_rewind_write(self):
+        # Various combinations of reading / writing / seeking backwards / writing again
+        def mutate(bufio, pos1, pos2):
+            assert pos2 >= pos1
+            # Fill the buffer
+            bufio.seek(pos1)
+            bufio.read(pos2 - pos1)
+            bufio.write(b'\x02')
+            # This writes earlier than the previous write, but still inside
+            # the buffer.
+            bufio.seek(pos1)
+            bufio.write(b'\x01')
+
+        b = b"\x80\x81\x82\x83\x84"
+        for i in range(0, len(b)):
+            for j in range(i, len(b)):
+                raw = self.BytesIO(b)
+                bufio = self.tp(raw, 100)
+                mutate(bufio, i, j)
+                bufio.flush()
+                expected = bytearray(b)
+                expected[j] = 2
+                expected[i] = 1
+                self.assertEqual(raw.getvalue(), expected,
+                                 "failed result for i=%d, j=%d" % (i, j))
+
     def test_truncate_after_read_or_write(self):
         raw = self.BytesIO(b"A" * 10)
         bufio = self.tp(raw, 100)
index 90f36a181eac752e665d573df839812b5bd31755..34f311bc9abfb46000a871f696cd231b054dccc4 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -80,6 +80,11 @@ Core and Builtins
 Library
 -------
 
+- Issue #12062: In the `io` module, fix a flushing bug when doing a certain
+  type of I/O sequence on a file opened in read+write mode (namely: reading,
+  seeking a bit forward, writing, then seeking before the previous write but
+  still within buffered data, and writing again).
+
 - Issue #8498: In socket.accept(), allow to specify 0 as a backlog value in
   order to accept exactly one connection.  Patch by Daniel Evers.
 
index 5816a934323eab4d29379b0291a34f388f5f48db..144aea20d8b249737fef363b0f64303db5765e6a 100644 (file)
@@ -1810,7 +1810,7 @@ bufferedwriter_write(buffered *self, PyObject *args)
     avail = Py_SAFE_DOWNCAST(self->buffer_size - self->pos, Py_off_t, Py_ssize_t);
     if (buf.len <= avail) {
         memcpy(self->buffer + self->pos, buf.buf, buf.len);
-        if (!VALID_WRITE_BUFFER(self)) {
+        if (!VALID_WRITE_BUFFER(self) || self->write_pos > self->pos) {
             self->write_pos = self->pos;
         }
         ADJUST_POSITION(self, self->pos + buf.len);