]> granicus.if.org Git - python/commitdiff
Issue #25688: Fixed file leak in ElementTree.iterparse() raising an error.
authorSerhiy Storchaka <storchaka@gmail.com>
Mon, 23 Nov 2015 13:44:03 +0000 (15:44 +0200)
committerSerhiy Storchaka <storchaka@gmail.com>
Mon, 23 Nov 2015 13:44:03 +0000 (15:44 +0200)
Lib/test/test_xml_etree.py
Lib/xml/etree/ElementTree.py
Misc/NEWS

index 8511cfe1572254ebeec288f0df419a8e11775a0b..5c2a2aff4027dc3f7c62b1648bd0826295551c8f 100644 (file)
@@ -561,11 +561,21 @@ class ElementTreeTest(unittest.TestCase):
         self.assertEqual(res, ['start-ns', 'end-ns'])
 
         events = ("start", "end", "bogus")
-        with self.assertRaises(ValueError) as cm:
-            with open(SIMPLE_XMLFILE, "rb") as f:
+        with open(SIMPLE_XMLFILE, "rb") as f:
+            with self.assertRaises(ValueError) as cm:
                 iterparse(f, events)
+            self.assertFalse(f.closed)
         self.assertEqual(str(cm.exception), "unknown event 'bogus'")
 
+        with warnings.catch_warnings(record=True) as w:
+            warnings.filterwarnings("always", category=ResourceWarning)
+            with self.assertRaises(ValueError) as cm:
+                iterparse(SIMPLE_XMLFILE, events)
+            self.assertEqual(str(cm.exception), "unknown event 'bogus'")
+            del cm
+            support.gc_collect()
+        self.assertEqual(w, [])
+
         source = io.BytesIO(
             b"<?xml version='1.0' encoding='iso-8859-1'?>\n"
             b"<body xmlns='http://&#233;ffbot.org/ns'\n"
@@ -586,6 +596,21 @@ class ElementTreeTest(unittest.TestCase):
         self.assertEqual(str(cm.exception),
                 'junk after document element: line 1, column 12')
 
+        with open(TESTFN, "wb") as f:
+            f.write(b"<document />junk")
+        it = iterparse(TESTFN)
+        action, elem = next(it)
+        self.assertEqual((action, elem.tag), ('end', 'document'))
+        with warnings.catch_warnings(record=True) as w:
+            warnings.filterwarnings("always", category=ResourceWarning)
+            with self.assertRaises(ET.ParseError) as cm:
+                next(it)
+            self.assertEqual(str(cm.exception),
+                    'junk after document element: line 1, column 12')
+            del cm, it
+            support.gc_collect()
+        self.assertEqual(w, [])
+
     def test_writefile(self):
         elem = ET.Element("tag")
         elem.text = "text"
index 97eba8bfcd63b31757a53ba32eb54c08725b605e..5a09b35da0872580ffeb984cfe5f76c72f6ba3aa 100644 (file)
@@ -1206,7 +1206,12 @@ def iterparse(source, events=None, parser=None):
     if not hasattr(source, "read"):
         source = open(source, "rb")
         close_source = True
-    return _IterParseIterator(source, events, parser, close_source)
+    try:
+        return _IterParseIterator(source, events, parser, close_source)
+    except:
+        if close_source:
+            source.close()
+        raise
 
 
 class XMLPullParser:
@@ -1289,20 +1294,26 @@ class _IterParseIterator:
         self.root = self._root = None
 
     def __next__(self):
-        while 1:
-            for event in self._parser.read_events():
-                return event
-            if self._parser._parser is None:
-                self.root = self._root
-                if self._close_file:
-                    self._file.close()
-                raise StopIteration
-            # load event buffer
-            data = self._file.read(16 * 1024)
-            if data:
-                self._parser.feed(data)
-            else:
-                self._root = self._parser._close_and_return_root()
+        try:
+            while 1:
+                for event in self._parser.read_events():
+                    return event
+                if self._parser._parser is None:
+                    break
+                # load event buffer
+                data = self._file.read(16 * 1024)
+                if data:
+                    self._parser.feed(data)
+                else:
+                    self._root = self._parser._close_and_return_root()
+            self.root = self._root
+        except:
+            if self._close_file:
+                self._file.close()
+            raise
+        if self._close_file:
+            self._file.close()
+        raise StopIteration
 
     def __iter__(self):
         return self
index dee83382363d7b7eb91294e0b7e41aba7f12b0d0..e3360239fa013dcafbed07ffc32e16d1f3536354 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -106,6 +106,8 @@ Core and Builtins
 Library
 -------
 
+- Issue #25688: Fixed file leak in ElementTree.iterparse() raising an error.
+
 - Issue #23914: Fixed SystemError raised by unpickler on broken pickle data.
 
 - Issue #25691: Fixed crash on deleting ElementTree.Element attributes.