Unverified Kaydet (Commit) 1d896ed2 authored tarafından Antoine Pitrou's avatar Antoine Pitrou Kaydeden (comit) GitHub

[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 059f58ce)
üst 33febfb0
...@@ -1703,6 +1703,23 @@ class BufferedWriterTest(unittest.TestCase, CommonBufferedTests): ...@@ -1703,6 +1703,23 @@ class BufferedWriterTest(unittest.TestCase, CommonBufferedTests):
with self.open(support.TESTFN, "rb", buffering=0) as f: with self.open(support.TESTFN, "rb", buffering=0) as f:
self.assertEqual(f.read(), b"abc") 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.') @unittest.skipUnless(threading, 'Threading required for this test.')
@support.requires_resource('cpu') @support.requires_resource('cpu')
def test_threads(self): def test_threads(self):
......
Ensure that ``truncate()`` preserves the file position (as reported by ``tell()``) after writes longer than the buffer size.
...@@ -1311,7 +1311,6 @@ _io__Buffered_seek_impl(buffered *self, PyObject *targetobj, int whence) ...@@ -1311,7 +1311,6 @@ _io__Buffered_seek_impl(buffered *self, PyObject *targetobj, int whence)
if (res == NULL) if (res == NULL)
goto end; goto end;
Py_CLEAR(res); Py_CLEAR(res);
_bufferedwriter_reset_buf(self);
} }
/* TODO: align on block boundary and read buffer if needed? */ /* 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) ...@@ -1878,8 +1877,6 @@ _bufferedwriter_raw_write(buffered *self, char *start, Py_ssize_t len)
return n; return n;
} }
/* `restore_pos` is 1 if we need to restore the raw stream position at
the end, 0 otherwise. */
static PyObject * static PyObject *
_bufferedwriter_flush_unlocked(buffered *self) _bufferedwriter_flush_unlocked(buffered *self)
{ {
...@@ -1920,9 +1917,18 @@ _bufferedwriter_flush_unlocked(buffered *self) ...@@ -1920,9 +1917,18 @@ _bufferedwriter_flush_unlocked(buffered *self)
goto error; goto error;
} }
_bufferedwriter_reset_buf(self);
end: 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; Py_RETURN_NONE;
error: error:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment