From 83cb76d008e9007830cdd713080b3f7a00a8d3b5 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 4 May 2017 01:53:05 +0200 Subject: [PATCH] bpo-30264: xml.sax.parse() closes the parser on error The xml.sax.parse() function now closes the parser on error to not leak resources like open files. --- Lib/test/test_sax.py | 8 ++------ Lib/xml/sax/__init__.py | 13 ++++++++++--- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/Lib/test/test_sax.py b/Lib/test/test_sax.py index 2411895d9d12b1c..c7eea6034188e55 100644 --- a/Lib/test/test_sax.py +++ b/Lib/test/test_sax.py @@ -175,12 +175,8 @@ def test_parse_bytes(self): with self.assertRaises(SAXException): self.check_parse(BytesIO(xml_bytes(self.data, 'iso-8859-1', None))) make_xml_file(self.data, 'iso-8859-1', None) - with support.check_warnings(('unclosed file', ResourceWarning)): - # XXX Failed parser leaks an opened file. - with self.assertRaises(SAXException): - self.check_parse(TESTFN) - # Collect leaked file. - gc.collect() + with self.assertRaises(SAXException): + self.check_parse(TESTFN) with open(TESTFN, 'rb') as f: with self.assertRaises(SAXException): self.check_parse(f) diff --git a/Lib/xml/sax/__init__.py b/Lib/xml/sax/__init__.py index ef67ae67a6bdd31..5f65e315866f3b3 100644 --- a/Lib/xml/sax/__init__.py +++ b/Lib/xml/sax/__init__.py @@ -28,9 +28,16 @@ def parse(source, handler, errorHandler=ErrorHandler()): parser = make_parser() - parser.setContentHandler(handler) - parser.setErrorHandler(errorHandler) - parser.parse(source) + try: + parser.setContentHandler(handler) + parser.setErrorHandler(errorHandler) + parser.parse(source) + except: + # Third party parsers can have no close() method + if hasattr(parser, 'close'): + # On error, close the parser to not leak resources like open files + parser.close() + raise def parseString(string, handler, errorHandler=ErrorHandler()): import io