]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.9] bpo-43292: Fix file leak in `ET.iterparse()` when not exhausted (GH-31696)...
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Mon, 7 Mar 2022 11:48:53 +0000 (03:48 -0800)
committerGitHub <noreply@github.com>
Mon, 7 Mar 2022 11:48:53 +0000 (13:48 +0200)
Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
(cherry picked from commit 496c428de3318c9c5770937491b71dc3d3f18a6a)

Co-authored-by: Jacob Walls <jacobtylerwalls@gmail.com>
Lib/test/test_xml_etree.py
Lib/xml/etree/ElementTree.py
Misc/ACKS
Misc/NEWS.d/next/Library/2022-03-05-09-43-53.bpo-25707.gTlclP.rst [new file with mode: 0644]

index 762b0bfed2c339dfeebfd4e70fa9d0954e751ccd..0f45fc71ce7736f44b1beee557084b888701883a 100644 (file)
@@ -640,6 +640,14 @@ class ElementTreeTest(unittest.TestCase):
                     'junk after document element: line 1, column 12')
             del cm, it
 
+        # Not exhausting the iterator still closes the resource (bpo-43292)
+        with support.check_no_resource_warning(self):
+            it = iterparse(TESTFN)
+            del it
+
+        with self.assertRaises(FileNotFoundError):
+            iterparse("nonexistent")
+
     def test_writefile(self):
         elem = ET.Element("tag")
         elem.text = "text"
index fde303c875ce8cc05ceed529015e9af7cf40657c..dae2251d859dafcc4de46fe2c6ea66774551b740 100644 (file)
@@ -1248,8 +1248,14 @@ def iterparse(source, events=None, parser=None):
     # Use the internal, undocumented _parser argument for now; When the
     # parser argument of iterparse is removed, this can be killed.
     pullparser = XMLPullParser(events=events, _parser=parser)
-    def iterator():
+
+    def iterator(source):
+        close_source = False
         try:
+            if not hasattr(source, "read"):
+                source = open(source, "rb")
+                close_source = True
+            yield None
             while True:
                 yield from pullparser.read_events()
                 # load event buffer
@@ -1265,16 +1271,12 @@ def iterparse(source, events=None, parser=None):
                 source.close()
 
     class IterParseIterator(collections.abc.Iterator):
-        __next__ = iterator().__next__
+        __next__ = iterator(source).__next__
     it = IterParseIterator()
     it.root = None
     del iterator, IterParseIterator
 
-    close_source = False
-    if not hasattr(source, "read"):
-        source = open(source, "rb")
-        close_source = True
-
+    next(it)
     return it
 
 
index c8d0be6999b78fa8e0356404c2bf5fe2d917f23c..2a26fdcd16b439d47944d2f481d59c33d1e2d862 100644 (file)
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -1836,6 +1836,7 @@ Wojtek Walczak
 Charles Waldman
 Richard Walker
 Larry Wall
+Jacob Walls
 Kevin Walzer
 Rodrigo Steinmuller Wanderley
 Dingyuan Wang
diff --git a/Misc/NEWS.d/next/Library/2022-03-05-09-43-53.bpo-25707.gTlclP.rst b/Misc/NEWS.d/next/Library/2022-03-05-09-43-53.bpo-25707.gTlclP.rst
new file mode 100644 (file)
index 0000000..a59f0a7
--- /dev/null
@@ -0,0 +1,2 @@
+Fixed a file leak in :func:`xml.etree.ElementTree.iterparse` when the
+iterator is not exhausted. Patch by Jacob Walls.