SF patch #755987 (Jim Ahlstrom):
This is a patch for Bug 755031: If a null byte appears in
a file name, Python zipfile.py retains it, but InfoZip
terminates the name. Null bytes in file names are used
as a trick by viruses. I tested WinZip, and it also
truncates the file name at the null byte.

The patch also fixes a buglet: If a zipfile incorrectly
uses a directory separator other than '/', there was an
invalid complaint that the central directory name does
not match the file header name.

I also removed my name from the top of the file. It was
there for legal reasons which I believe no longer apply.
Many people have worked on this file besides me.
diff --git a/Lib/zipfile.py b/Lib/zipfile.py
index 80d7925..576eaf9 100644
--- a/Lib/zipfile.py
+++ b/Lib/zipfile.py
@@ -1,6 +1,4 @@
 "Read and write ZIP files."
-# Written by James C. Ahlstrom jim@interet.com
-# All rights transferred to CNRI pursuant to the Python contribution agreement
 
 import struct, os, time
 import binascii
@@ -116,7 +114,19 @@
     """Class with attributes describing each file in the ZIP archive."""
 
     def __init__(self, filename="NoName", date_time=(1980,1,1,0,0,0)):
-        self.filename = _normpath(filename) # Name of the file in the archive
+        self.orig_filename = filename   # Original file name in archive
+# Terminate the file name at the first null byte.  Null bytes in file
+# names are used as tricks by viruses in archives.
+        null_byte = filename.find(chr(0))
+        if null_byte >= 0:
+            filename = filename[0:null_byte]
+            print "File name %s contains a suspicious null byte!" % filename
+# This is used to ensure paths in generated ZIP files always use
+# forward slashes as the directory separator, as required by the
+# ZIP format specification.
+        if os.sep != "/":
+            filename = filename.replace(os.sep, "/")
+        self.filename = filename        # Normalized file name
         self.date_time = date_time      # year, month, day, hour, min, sec
         # Standard values:
         self.compress_type = ZIP_STORED # Type of compression for the file
@@ -157,17 +167,6 @@
         return header + self.filename + self.extra
 
 
-# This is used to ensure paths in generated ZIP files always use
-# forward slashes as the directory separator, as required by the
-# ZIP format specification.
-if os.sep != "/":
-    def _normpath(path):
-        return path.replace(os.sep, "/")
-else:
-    def _normpath(path):
-        return path
-
-
 class ZipFile:
     """ Class with methods to open, read, write, close, list zip files.
 
@@ -300,10 +299,10 @@
                                 + fheader[_FH_FILENAME_LENGTH]
                                 + fheader[_FH_EXTRA_FIELD_LENGTH])
             fname = fp.read(fheader[_FH_FILENAME_LENGTH])
-            if fname != data.filename:
+            if fname != data.orig_filename:
                 raise RuntimeError, \
                       'File name in directory "%s" and header "%s" differ.' % (
-                          data.filename, fname)
+                          data.orig_filename, fname)
 
     def namelist(self):
         """Return a list of file names in the archive."""