diff -r 6fb033af9310 Lib/test/test_pyexpat.py --- a/Lib/test/test_pyexpat.py Fri Apr 08 11:40:38 2011 +0100 +++ b/Lib/test/test_pyexpat.py Sat Apr 09 04:24:23 2011 +0300 @@ -6,6 +6,7 @@ from xml.parsers import expat +from test import test_support from test.test_support import sortdict, run_unittest @@ -217,6 +218,16 @@ self.assertEqual(op[15], "External entity ref: (None, u'entity.file', None)") self.assertEqual(op[16], "End element: u'root'") + # Issue 4877: expat.ParseFile causes segfault on a closed file. + fp = open(test_support.TESTFN, 'wb') + try: + fp.close() + parser = expat.ParserCreate() + with self.assertRaises(ValueError): + parser.ParseFile(fp) + finally: + test_support.unlink(test_support.TESTFN) + class NamespaceSeparatorTest(unittest.TestCase): def test_legal(self): diff -r 6fb033af9310 Modules/pyexpat.c --- a/Modules/pyexpat.c Fri Apr 08 11:40:38 2011 +0100 +++ b/Modules/pyexpat.c Sat Apr 09 04:24:23 2011 +0300 @@ -962,21 +962,15 @@ xmlparse_ParseFile(xmlparseobject *self, PyObject *f) { int rv = 1; - FILE *fp; PyObject *readmethod = NULL; - if (PyFile_Check(f)) { - fp = PyFile_AsFile(f); - } - else { - fp = NULL; - readmethod = PyObject_GetAttrString(f, "read"); - if (readmethod == NULL) { - PyErr_Clear(); - PyErr_SetString(PyExc_TypeError, - "argument must have 'read' attribute"); - return NULL; - } + readmethod = PyObject_GetAttrString(f, "read"); + if (readmethod == NULL) { + PyErr_Clear(); + PyErr_SetString(PyExc_TypeError, + "argument must have 'read' attribute"); + return NULL; + } for (;;) { int bytes_read; @@ -986,20 +980,12 @@ return PyErr_NoMemory(); } - if (fp) { - bytes_read = fread(buf, sizeof(char), BUF_SIZE, fp); - if (bytes_read < 0) { - PyErr_SetFromErrno(PyExc_IOError); - return NULL; - } + bytes_read = readinst(buf, BUF_SIZE, readmethod); + if (bytes_read < 0) { + Py_XDECREF(readmethod); + return NULL; } - else { - bytes_read = readinst(buf, BUF_SIZE, readmethod); - if (bytes_read < 0) { - Py_XDECREF(readmethod); - return NULL; - } - } + rv = XML_ParseBuffer(self->itself, bytes_read, bytes_read == 0); if (PyErr_Occurred()) { Py_XDECREF(readmethod);