From 36d480146312efd69d37f98336f2cf0882b89c30 Mon Sep 17 00:00:00 2001 From: Guido Draheim Date: Mon, 22 Jun 2009 14:27:11 +0000 Subject: [PATCH] rework parse_directory to allow for ZZIP_ALLOW_MODULO_ENTRIES --- ChangeLog | 8 ++++++++ zzip/zip.c | 28 +++++++++++++++++++++++++--- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index bcaa32a..698647e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,13 @@ 2009-06-22 guidod + * 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?) diff --git a/zzip/zip.c b/zzip/zip.c index 8cd6687..0a400cd 100644 --- a/zzip/zip.c +++ b/zzip/zip.c @@ -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 ------------------------- */ -- 2.40.0