summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAntoine Pitrou <solipsis@pitrou.net>2010-08-01 20:08:46 (GMT)
committerAntoine Pitrou <solipsis@pitrou.net>2010-08-01 20:08:46 (GMT)
commit7ffa196dce8db3010bce3e550078ed455a30e851 (patch)
treeec5119d3f4e2b23c8c1b07af8c5e453f6f4a7949
parent7fb6f5121a42136f35c561c408091cd043f6340d (diff)
downloadcpython-7ffa196dce8db3010bce3e550078ed455a30e851.zip
cpython-7ffa196dce8db3010bce3e550078ed455a30e851.tar.gz
cpython-7ffa196dce8db3010bce3e550078ed455a30e851.tar.bz2
Issue #8397: Raise an error when attempting to mix iteration and regular
reads on a BZ2File object, rather than returning incorrect results.
-rw-r--r--Lib/test/test_bz2.py18
-rw-r--r--Misc/NEWS3
-rw-r--r--Modules/bz2module.c28
3 files changed, 49 insertions, 0 deletions
diff --git a/Lib/test/test_bz2.py b/Lib/test/test_bz2.py
index 63b3009..0826458 100644
--- a/Lib/test/test_bz2.py
+++ b/Lib/test/test_bz2.py
@@ -304,6 +304,24 @@ class BZ2FileTest(BaseTest):
finally:
f.close()
+ def testMixedIterationReads(self):
+ # Issue #8397: mixed iteration and reads should be forbidden.
+ f = bz2.BZ2File(self.filename, 'wb')
+ try:
+ # The internal buffer size is hard-wired to 8192 bytes, we must
+ # write out more than that for the test to stop half through
+ # the buffer.
+ f.write(self.TEXT * 100)
+ finally:
+ f.close()
+ f = bz2.BZ2File(self.filename, 'rb')
+ try:
+ next(f)
+ self.assertRaises(ValueError, f.read)
+ self.assertRaises(ValueError, f.readline)
+ self.assertRaises(ValueError, f.readlines)
+ finally:
+ f.close()
class BZ2CompressorTest(BaseTest):
def testCompress(self):
diff --git a/Misc/NEWS b/Misc/NEWS
index 7d1317d..1126d4a 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -29,6 +29,9 @@ Extensions
Library
-------
+- Issue #8397: Raise an error when attempting to mix iteration and regular
+ reads on a BZ2File object, rather than returning incorrect results.
+
- Issue #9448: Fix a leak of OS resources (mutexes or semaphores) when
re-initializing a buffered IO object by calling its ``__init__`` method.
diff --git a/Modules/bz2module.c b/Modules/bz2module.c
index 29f8592..c44d3b9 100644
--- a/Modules/bz2module.c
+++ b/Modules/bz2module.c
@@ -138,6 +138,22 @@ typedef struct {
/* ===================================================================== */
/* Utility functions. */
+/* Refuse regular I/O if there's data in the iteration-buffer.
+ * Mixing them would cause data to arrive out of order, as the read*
+ * methods don't use the iteration buffer. */
+static int
+check_iterbuffered(BZ2FileObject *f)
+{
+ if (f->f_buf != NULL &&
+ (f->f_bufend - f->f_bufptr) > 0 &&
+ f->f_buf[0] != '\0') {
+ PyErr_SetString(PyExc_ValueError,
+ "Mixing iteration and read methods would lose data");
+ return -1;
+ }
+ return 0;
+}
+
static int
Util_CatchBZ2Error(int bzerror)
{
@@ -427,6 +443,10 @@ BZ2File_read(BZ2FileObject *self, PyObject *args)
goto cleanup;
}
+ /* refuse to mix with f.next() */
+ if (check_iterbuffered(self))
+ goto cleanup;
+
if (bytesrequested < 0)
buffersize = Util_NewBufferSize((size_t)0);
else
@@ -516,6 +536,10 @@ BZ2File_readline(BZ2FileObject *self, PyObject *args)
goto cleanup;
}
+ /* refuse to mix with f.next() */
+ if (check_iterbuffered(self))
+ goto cleanup;
+
if (sizehint == 0)
ret = PyBytes_FromStringAndSize("", 0);
else
@@ -573,6 +597,10 @@ BZ2File_readlines(BZ2FileObject *self, PyObject *args)
goto cleanup;
}
+ /* refuse to mix with f.next() */
+ if (check_iterbuffered(self))
+ goto cleanup;
+
if ((list = PyList_New(0)) == NULL)
goto cleanup;