From 3970301e93ec3ab2e9a7a4c992d7056bea3ff9f6 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Sun, 1 Aug 2010 20:13:11 +0000 Subject: [PATCH] Merged revisions 83440 via svnmerge from svn+ssh://pythondev@svn.python.org/python/branches/py3k MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ........ r83440 | antoine.pitrou | 2010-08-01 22:08:46 +0200 (dim., 01 août 2010) | 4 lines Issue #8397: Raise an error when attempting to mix iteration and regular reads on a BZ2File object, rather than returning incorrect results. ........ --- Lib/test/test_bz2.py | 18 ++++++++++++++++++ Misc/NEWS | 3 +++ Modules/bz2module.c | 28 ++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+) diff --git a/Lib/test/test_bz2.py b/Lib/test/test_bz2.py index 555cdeba23e..c7ef320aa4f 100644 --- a/Lib/test/test_bz2.py +++ b/Lib/test/test_bz2.py @@ -329,6 +329,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 fb3e59e543c..3326e067ffb 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -24,6 +24,9 @@ Core and Builtins Library ------- +- Issue #8397: Raise an error when attempting to mix iteration and regular + reads on a BZ2File object, rather than returning incorrect results. + - Issue #5294: Fix the behavior of pdb's "continue" command when called in the top-level debugged frame. diff --git a/Modules/bz2module.c b/Modules/bz2module.c index 8e0976691d2..0a367a77696 100644 --- a/Modules/bz2module.c +++ b/Modules/bz2module.c @@ -144,6 +144,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) { @@ -527,6 +543,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 @@ -612,6 +632,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 = PyString_FromString(""); else @@ -669,6 +693,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;