Sf bug [ #412214 ] ZipFile constructor leaves files open.
authorTim Peters <tim.peters@gmail.com>
Wed, 4 Apr 2001 18:56:49 +0000 (18:56 +0000)
committerTim Peters <tim.peters@gmail.com>
Wed, 4 Apr 2001 18:56:49 +0000 (18:56 +0000)
This applies the patch Fred Drake created to fix it.
I'm checking it in since I had to apply the patch anyway in order
to test its behavior on Windows.

Lib/test/test_zipfile.py
Lib/zipfile.py

index 50b8b36a859e72fb44c3f46f757742c00497f429..bf7770b8cb9fbf1f242043a488bf0cfe3c481587 100644 (file)
@@ -42,6 +42,22 @@ finally:
     if os.path.isfile(zipname):
         os.unlink(zipname)
 
+
+# This test checks that the ZipFile constructor closes the file object
+# it opens if there's an error in the file.  If it doesn't, the traceback
+# holds a reference to the ZipFile object and, indirectly, the file object.
+# On Windows, this causes the os.unlink() call to fail because the
+# underlying file is still open.  This is SF bug #412214.
+#
+fp = open(srcname, "w")
+fp.write("this is not a legal zip file\n")
+fp.close()
+try:
+    zf = zipfile.ZipFile(srcname)
+except zipfile.BadZipfile:
+    os.unlink(srcname)
+
+
 # make sure we don't raise an AttributeError when a partially-constructed
 # ZipFile instance is finalized; this tests for regression on SF tracker
 # bug #403871.
index b638592a7a3ec26e2cedbeaf68f88d3ed33ff7d9..5dedc1ba8cb922352f52fc15d5301b104a1e582c 100644 (file)
@@ -186,9 +186,23 @@ class ZipFile:
             else:               # file is not a zip file, just append
                 fp.seek(0, 2)
         else:
+            if not self._filePassed:
+                self.fp.close()
+                self.fp = None
             raise RuntimeError, 'Mode must be "r", "w" or "a"'
 
     def _GetContents(self):
+        """Read the directory, making sure we close the file if the format
+        is bad."""
+        try:
+            self._RealGetContents()
+        except BadZipfile:
+            if not self._filePassed:
+                self.fp.close()
+                self.fp = None
+            raise
+
+    def _RealGetContents(self):
         """Read in the table of contents for the ZIP file."""
         fp = self.fp
         fp.seek(-22, 2)         # Start of end-of-archive record