Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 00dd182

Browse files
committed
Issue #12062: 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).
2 parents b00d0c4 + 7c40489 commit 00dd182

3 files changed

Lines changed: 33 additions & 1 deletion

File tree

Lib/test/test_io.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1490,6 +1490,32 @@ def test_write_after_readahead(self):
14901490
self.assertEqual(s,
14911491
b"A" + b"B" * overwrite_size + b"A" * (9 - overwrite_size))
14921492

1493+
def test_write_rewind_write(self):
1494+
# Various combinations of reading / writing / seeking backwards / writing again
1495+
def mutate(bufio, pos1, pos2):
1496+
assert pos2 >= pos1
1497+
# Fill the buffer
1498+
bufio.seek(pos1)
1499+
bufio.read(pos2 - pos1)
1500+
bufio.write(b'\x02')
1501+
# This writes earlier than the previous write, but still inside
1502+
# the buffer.
1503+
bufio.seek(pos1)
1504+
bufio.write(b'\x01')
1505+
1506+
b = b"\x80\x81\x82\x83\x84"
1507+
for i in range(0, len(b)):
1508+
for j in range(i, len(b)):
1509+
raw = self.BytesIO(b)
1510+
bufio = self.tp(raw, 100)
1511+
mutate(bufio, i, j)
1512+
bufio.flush()
1513+
expected = bytearray(b)
1514+
expected[j] = 2
1515+
expected[i] = 1
1516+
self.assertEqual(raw.getvalue(), expected,
1517+
"failed result for i=%d, j=%d" % (i, j))
1518+
14931519
def test_truncate_after_read_or_write(self):
14941520
raw = self.BytesIO(b"A" * 10)
14951521
bufio = self.tp(raw, 100)

Misc/NEWS

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,12 @@ Core and Builtins
8989

9090
Library
9191
-------
92+
93+
- Issue #12062: Fix a flushing bug when doing a certain type of I/O sequence
94+
on a file opened in read+write mode (namely: reading, seeking a bit forward,
95+
writing, then seeking before the previous write but still within buffered
96+
data, and writing again).
97+
9298
- Issue #1028: Tk returns invalid Unicode null in %A: UnicodeDecodeError.
9399
With Tk < 8.5 _tkinter.c:PythonCmd() raised UnicodeDecodeError, caused
94100
IDLE to exit. Converted to valid Unicode null in PythonCmd().

Modules/_io/bufferedio.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1838,7 +1838,7 @@ bufferedwriter_write(buffered *self, PyObject *args)
18381838
avail = Py_SAFE_DOWNCAST(self->buffer_size - self->pos, Py_off_t, Py_ssize_t);
18391839
if (buf.len <= avail) {
18401840
memcpy(self->buffer + self->pos, buf.buf, buf.len);
1841-
if (!VALID_WRITE_BUFFER(self)) {
1841+
if (!VALID_WRITE_BUFFER(self) || self->write_pos > self->pos) {
18421842
self->write_pos = self->pos;
18431843
}
18441844
ADJUST_POSITION(self, self->pos + buf.len);

0 commit comments

Comments
 (0)