[Python-checkins] [3.6] bpo-32228: Reset raw_pos after unwinding the raw stream (GH-4858) (#5389)
Antoine Pitrou
webhook-mailer at python.org
Sun Jan 28 12:42:34 EST 2018
https://github.com/python/cpython/commit/1d896ed2cddada4455f40782e4120249defbfa70
commit: 1d896ed2cddada4455f40782e4120249defbfa70
branch: 3.6
author: Antoine Pitrou <pitrou at free.fr>
committer: GitHub <noreply at github.com>
date: 2018-01-28T18:42:31+01:00
summary:
[3.6] bpo-32228: Reset raw_pos after unwinding the raw stream (GH-4858) (#5389)
Ensure that ``truncate()`` preserves the file position (as reported by ``tell()``) after writes longer than the buffer size..
(cherry picked from commit 059f58ce938d9c3f0286412a4efb1b9131339421)
files:
A Misc/NEWS.d/next/Library/2017-12-22-16-47-41.bpo-32228.waPx3q.rst
M Lib/test/test_io.py
M Modules/_io/bufferedio.c
diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py
index 42dbbd35dc95..6c30a44e62a6 100644
--- a/Lib/test/test_io.py
+++ b/Lib/test/test_io.py
@@ -1703,6 +1703,23 @@ def test_truncate(self):
with self.open(support.TESTFN, "rb", buffering=0) as f:
self.assertEqual(f.read(), b"abc")
+ def test_truncate_after_write(self):
+ # Ensure that truncate preserves the file position after
+ # writes longer than the buffer size.
+ # Issue: https://bugs.python.org/issue32228
+ with self.open(support.TESTFN, "wb") as f:
+ # Fill with some buffer
+ f.write(b'\x00' * 10000)
+ buffer_sizes = [8192, 4096, 200]
+ for buffer_size in buffer_sizes:
+ with self.open(support.TESTFN, "r+b", buffering=buffer_size) as f:
+ f.write(b'\x00' * (buffer_size + 1))
+ # After write write_pos and write_end are set to 0
+ f.read(1)
+ # read operation makes sure that pos != raw_pos
+ f.truncate()
+ self.assertEqual(f.tell(), buffer_size + 2)
+
@unittest.skipUnless(threading, 'Threading required for this test.')
@support.requires_resource('cpu')
def test_threads(self):
diff --git a/Misc/NEWS.d/next/Library/2017-12-22-16-47-41.bpo-32228.waPx3q.rst b/Misc/NEWS.d/next/Library/2017-12-22-16-47-41.bpo-32228.waPx3q.rst
new file mode 100644
index 000000000000..3bbe7c495f82
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2017-12-22-16-47-41.bpo-32228.waPx3q.rst
@@ -0,0 +1 @@
+Ensure that ``truncate()`` preserves the file position (as reported by ``tell()``) after writes longer than the buffer size.
diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c
index efc7d05b7d01..32355813e88d 100644
--- a/Modules/_io/bufferedio.c
+++ b/Modules/_io/bufferedio.c
@@ -1311,7 +1311,6 @@ _io__Buffered_seek_impl(buffered *self, PyObject *targetobj, int whence)
if (res == NULL)
goto end;
Py_CLEAR(res);
- _bufferedwriter_reset_buf(self);
}
/* TODO: align on block boundary and read buffer if needed? */
@@ -1878,8 +1877,6 @@ _bufferedwriter_raw_write(buffered *self, char *start, Py_ssize_t len)
return n;
}
-/* `restore_pos` is 1 if we need to restore the raw stream position at
- the end, 0 otherwise. */
static PyObject *
_bufferedwriter_flush_unlocked(buffered *self)
{
@@ -1920,9 +1917,18 @@ _bufferedwriter_flush_unlocked(buffered *self)
goto error;
}
- _bufferedwriter_reset_buf(self);
end:
+ /* This ensures that after return from this function,
+ VALID_WRITE_BUFFER(self) returns false.
+
+ This is a required condition because when a tell() is called
+ after flushing and if VALID_READ_BUFFER(self) is false, we need
+ VALID_WRITE_BUFFER(self) to be false to have
+ RAW_OFFSET(self) == 0.
+
+ Issue: https://bugs.python.org/issue32228 */
+ _bufferedwriter_reset_buf(self);
Py_RETURN_NONE;
error:
More information about the Python-checkins
mailing list