Index: Lib/test/test_bz2.py =================================================================== --- Lib/test/test_bz2.py (révision 83410) +++ Lib/test/test_bz2.py (copie de travail) @@ -304,6 +304,24 @@ 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): Index: Modules/bz2module.c =================================================================== --- Modules/bz2module.c (révision 83410) +++ Modules/bz2module.c (copie de travail) @@ -138,7 +138,23 @@ /* ===================================================================== */ /* 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) { int ret = 0; @@ -427,6 +443,10 @@ 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 @@ 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 @@ goto cleanup; } + /* refuse to mix with f.next() */ + if (check_iterbuffered(self)) + goto cleanup; + if ((list = PyList_New(0)) == NULL) goto cleanup;