From 337c50b8cb84155918ff0b4b5478c70f7a6f3faf Mon Sep 17 00:00:00 2001 From: Nadeem Vawda Date: Sun, 8 Dec 2013 15:31:50 +0100 Subject: [PATCH] Closes #19878: Fix segfault in bz2 module. Initial patch by Vajrasky Kok. --- Lib/test/test_bz2.py | 12 ++++++++++++ Misc/NEWS | 3 +++ Modules/bz2module.c | 17 ++++++++++------- 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/Lib/test/test_bz2.py b/Lib/test/test_bz2.py index 1275114664..a981d28002 100644 --- a/Lib/test/test_bz2.py +++ b/Lib/test/test_bz2.py @@ -325,6 +325,18 @@ class BZ2FileTest(BaseTest): self.assertRaises(ValueError, f.readline) self.assertRaises(ValueError, f.readlines) + def testInitNonExistentFile(self): + # Issue #19878: Should not segfault when __init__ with non-existent + # file for the second time. + self.createTempFile() + # Test close(): + with BZ2File(self.filename, "wb") as f: + self.assertRaises(IOError, f.__init__, "non-existent-file") + # Test object deallocation without call to close(): + f = bz2.BZ2File(self.filename) + self.assertRaises(IOError, f.__init__, "non-existent-file") + del f + class BZ2CompressorTest(BaseTest): def testCompress(self): # "Test BZ2Compressor.compress()/flush()" diff --git a/Misc/NEWS b/Misc/NEWS index 059f7bfe09..928a18ed26 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -15,6 +15,9 @@ Core and Builtins Library ------- +- Issue #19878: Fix segfault in bz2 module after calling __init__ twice with + non-existent filename. Initial patch by Vajrasky Kok. + - Issue #16373: Prevent infinite recursion for ABC Set class comparisons. - Issue #19138: doctest's IGNORE_EXCEPTION_DETAIL now allows a match when diff --git a/Modules/bz2module.c b/Modules/bz2module.c index 4083fdfb68..e479777a1b 100644 --- a/Modules/bz2module.c +++ b/Modules/bz2module.c @@ -1206,12 +1206,16 @@ BZ2File_close(BZ2FileObject *self) 0, NULL, NULL); break; } - if (self->fp) { - PyFile_DecUseCount((PyFileObject *)self->file); - self->fp = NULL; + if (self->file) { + if (self->fp) + PyFile_DecUseCount((PyFileObject *)self->file); + ret = PyObject_CallMethod(self->file, "close", NULL); + } else { + Py_INCREF(Py_None); + ret = Py_None; } + self->fp = NULL; self->mode = MODE_CLOSED; - ret = PyObject_CallMethod(self->file, "close", NULL); if (bzerror != BZ_OK) { Util_CatchBZ2Error(bzerror); Py_XDECREF(ret); @@ -1479,10 +1483,9 @@ BZ2File_dealloc(BZ2FileObject *self) 0, NULL, NULL); break; } - if (self->fp) { + if (self->fp != NULL && self->file != NULL) PyFile_DecUseCount((PyFileObject *)self->file); - self->fp = NULL; - } + self->fp = NULL; Util_DropReadAhead(self); Py_XDECREF(self->file); Py_TYPE(self)->tp_free((PyObject *)self); -- 2.50.1