]> granicus.if.org Git - zziplib/commitdiff
rework parse_directory to allow for ZZIP_ALLOW_MODULO_ENTRIES
authorGuido Draheim <guidod@gmx.de>
Mon, 22 Jun 2009 14:27:11 +0000 (14:27 +0000)
committerGuido Draheim <guidod@gmx.de>
Mon, 22 Jun 2009 14:27:11 +0000 (14:27 +0000)
ChangeLog
zzip/zip.c

index bcaa32a337a3050c0584c3a0361efb4823754156..698647e215fcce80de980def524630553f2fdc26 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,13 @@
 2009-06-22  guidod  <guidod@gmx.de>
 
+       * zzip/zip.c (__zzip_parse_root_directory): rework parse_directory
+          to allow for ZZIP_ALLOW_MODULO_ENTRIES version as required for
+          some cases where more than 65535 entries are packed into a
+          non-ZIP64 archive. The modulo_entries variant is disabled by
+          default but the know for the problem space was put into code to
+          check for two more error conditions and report them in debug mode.
+          (problem space was described carefully by Tulipánt Gergely and
+           the provided patch was a good foundation for the ifdef code)
        * configure.ac: use $can_build_shared from linker-config to allow
            build on platforms that do not support a shared library concept
            or where it is disabled (the commandline switch overrides it?)
index 8cd6687b6c94eceb585cad6fe7112456062bff35..0a400cd47d84dad31f43865bc4bbf0f0c51d223f 100644 (file)
@@ -436,11 +436,21 @@ __zzip_parse_root_directory(int fd,
         }
     }
 
-    for (entries = zz_entries, zz_offset = 0; entries; entries--)
+    for (entries=0, zz_offset=0; ; entries++)
     {
         register struct zzip_disk_entry *d;
         uint16_t u_extras, u_comment, u_namlen;
 
+#     ifndef ZZIP_ALLOW_MODULO_ENTRIES
+        if (entries >= zz_entries) {
+            if (zz_offset + 256 < zz_rootsize) {
+                FAIL4("%li's entry is long before the end of directory - enable modulo_entries? (O:%li R:%li)",
+                      (long) entries, (long) (zz_offset), (long) zz_rootsize);
+            }
+            break;
+        }
+#     endif
+
         if (fd_map)
             { d = (void*)(fd_map+zz_fd_gap+zz_offset); } /* fd_map+fd_gap==u_rootseek */
         else
@@ -452,6 +462,14 @@ __zzip_parse_root_directory(int fd,
             d = &dirent;
         }
 
+        if (! zzip_disk_entry_check_magic(d)) {
+#        ifndef ZZIP_ALLOW_MODULO_ENTRIES
+            FAIL4("%li's entry has no disk_entry magic indicator (O:%li R:%li)",
+                  (long) entries, (long) (zz_offset), (long) zz_rootsize);
+#        endif
+            break;
+        }
+
         if ((zzip_off64_t) (zz_offset + sizeof(*d)) > zz_rootsize ||
             (zzip_off64_t) (zz_offset + sizeof(*d)) < 0)
         {
@@ -506,7 +524,7 @@ __zzip_parse_root_directory(int fd,
         {
             FAIL3("%li's entry stretches beyond root directory (O:%li)",
                   (long) entries, (long) (zz_offset));
-            entries--;
+            entries ++;
             break;
         }
 
@@ -540,7 +558,11 @@ __zzip_parse_root_directory(int fd,
         if (hdr_return)
             *hdr_return = hdr0;
     }                           /* else zero (sane) entries */
-    return (entries ? ZZIP_CORRUPTED : 0);
+#  ifndef ZZIP_ALLOW_MODULO_ENTRIES
+    return (entries != zz_entries ? ZZIP_CORRUPTED : 0);
+#  else
+    return (entries & (unsigned)0xFFFF) != zz_entries ? ZZIP_CORRUPTED : 0);
+#  endif
 }
 
 /* ------------------------- high-level interface ------------------------- */