diff --git a/libc/str/getzipcfilecompressedsize.c b/libc/str/getzipcfilecompressedsize.c index aaa7c86da4b..0523a631aac 100644 --- a/libc/str/getzipcfilecompressedsize.c +++ b/libc/str/getzipcfilecompressedsize.c @@ -27,7 +27,7 @@ int64_t GetZipCfileCompressedSize(const uint8_t *z) { } const uint8_t *p = ZIP_CFILE_EXTRA(z); const uint8_t *pe = p + ZIP_CFILE_EXTRASIZE(z); - for (; p < pe; p += ZIP_EXTRA_SIZE(p)) { + for (; p + ZIP_EXTRA_SIZE(p) <= pe; p += ZIP_EXTRA_SIZE(p)) { if (ZIP_EXTRA_HEADERID(p) == kZipExtraZip64) { if (8 <= ZIP_EXTRA_CONTENTSIZE(p)) { return READ64LE(ZIP_EXTRA_CONTENT(p)); diff --git a/libc/str/getzipcfileoffset.c b/libc/str/getzipcfileoffset.c index 3ce6c6d3e8d..8ece121c3ef 100644 --- a/libc/str/getzipcfileoffset.c +++ b/libc/str/getzipcfileoffset.c @@ -27,7 +27,7 @@ int64_t GetZipCfileOffset(const uint8_t *z) { } const uint8_t *p = ZIP_CFILE_EXTRA(z); const uint8_t *pe = p + ZIP_CFILE_EXTRASIZE(z); - for (; p < pe; p += ZIP_EXTRA_SIZE(p)) { + for (; p + ZIP_EXTRA_SIZE(p) <= pe; p += ZIP_EXTRA_SIZE(p)) { if (ZIP_EXTRA_HEADERID(p) == kZipExtraZip64) { int offset = 0; if (ZIP_CFILE_COMPRESSEDSIZE(z) == 0xFFFFFFFFu) { diff --git a/libc/str/getzipcfileuncompressedsize.c b/libc/str/getzipcfileuncompressedsize.c index 95cd0f33331..c410fffdfc1 100644 --- a/libc/str/getzipcfileuncompressedsize.c +++ b/libc/str/getzipcfileuncompressedsize.c @@ -27,7 +27,7 @@ int64_t GetZipCfileUncompressedSize(const uint8_t *z) { } const uint8_t *p = ZIP_CFILE_EXTRA(z); const uint8_t *pe = p + ZIP_CFILE_EXTRASIZE(z); - for (; p < pe; p += ZIP_EXTRA_SIZE(p)) { + for (; p + ZIP_EXTRA_SIZE(p) <= pe; p += ZIP_EXTRA_SIZE(p)) { if (ZIP_EXTRA_HEADERID(p) == kZipExtraZip64) { int offset = 0; if (ZIP_CFILE_COMPRESSEDSIZE(z) == 0xFFFFFFFFu) { diff --git a/libc/str/getziplfilecompressedsize.c b/libc/str/getziplfilecompressedsize.c index a170c66120e..c398dfe9810 100644 --- a/libc/str/getziplfilecompressedsize.c +++ b/libc/str/getziplfilecompressedsize.c @@ -27,7 +27,7 @@ int64_t GetZipLfileCompressedSize(const uint8_t *z) { } const uint8_t *p = ZIP_LFILE_EXTRA(z); const uint8_t *pe = p + ZIP_LFILE_EXTRASIZE(z); - for (; p < pe; p += ZIP_EXTRA_SIZE(p)) { + for (; p + ZIP_EXTRA_SIZE(p) <= pe; p += ZIP_EXTRA_SIZE(p)) { if (ZIP_EXTRA_HEADERID(p) == kZipExtraZip64) { if (8 <= ZIP_EXTRA_CONTENTSIZE(p)) { return READ64LE(ZIP_EXTRA_CONTENT(p)); diff --git a/libc/str/getziplfileuncompressedsize.c b/libc/str/getziplfileuncompressedsize.c index 2e245aba58e..13b23f1d485 100644 --- a/libc/str/getziplfileuncompressedsize.c +++ b/libc/str/getziplfileuncompressedsize.c @@ -27,7 +27,7 @@ int64_t GetZipLfileUncompressedSize(const uint8_t *z) { } const uint8_t *p = ZIP_LFILE_EXTRA(z); const uint8_t *pe = p + ZIP_LFILE_EXTRASIZE(z); - for (; p < pe; p += ZIP_EXTRA_SIZE(p)) { + for (; p + ZIP_EXTRA_SIZE(p) <= pe; p += ZIP_EXTRA_SIZE(p)) { if (ZIP_EXTRA_HEADERID(p) == kZipExtraZip64) { int offset = 0; if (ZIP_LFILE_COMPRESSEDSIZE(z) == 0xFFFFFFFFu) { diff --git a/libc/zip.internal.h b/libc/zip.internal.h index 245add37a31..58b49098be1 100644 --- a/libc/zip.internal.h +++ b/libc/zip.internal.h @@ -89,6 +89,8 @@ #define kZipCfileHdrMagic ZM_(0x02014b50) /* PK☺☻ "PK\1\2" */ #define kZipCfileHdrMinSize 46 +#define kZipCfileOffsetVersionMadeBy 4 +#define kZipCfileOffsetVersionNeeded 6 #define kZipCfileOffsetGeneralflag 8 #define kZipCfileOffsetCompressionmethod 10 #define kZipCfileOffsetLastmodifiedtime 12 diff --git a/tool/build/apelink.c b/tool/build/apelink.c index 4358d0ed12d..65ccb2e00b5 100644 --- a/tool/build/apelink.c +++ b/tool/build/apelink.c @@ -674,9 +674,10 @@ static void LoadSymbols(Elf64_Ehdr *e, Elf64_Off size, const char *path) { unsigned char *cfile = Malloc(cfile_size); bzero(cfile, cfile_size); WRITE32LE(cfile, kZipCfileHdrMagic); - cfile[4] = kZipCosmopolitanVersion; - cfile[5] = kZipOsUnix; - cfile[6] = kZipEra2001; + WRITE16LE(cfile + kZipCfileOffsetVersionMadeBy, + kZipOsUnix << 8 | kZipCosmopolitanVersion); + WRITE16LE(cfile + kZipCfileOffsetVersionNeeded, kZipEra2001); + WRITE16LE(cfile + kZipCfileOffsetGeneralflag, kZipGflagUtf8); WRITE16LE(cfile + kZipCfileOffsetCompressionmethod, kZipCompressionDeflate); WRITE16LE(cfile + kZipCfileOffsetLastmodifieddate, DOS_DATE(2023, 7, 29)); WRITE16LE(cfile + kZipCfileOffsetLastmodifiedtime, DOS_TIME(0, 0, 0)); @@ -1813,9 +1814,11 @@ int main(int argc, char *argv[]) { int i, j; Elf64_Off offset; Elf64_Xword prologue_bytes; -#ifndef NDEBUG + +#ifdef MODE_DBG ShowCrashReports(); #endif + prog = argv[0]; if (!prog) prog = "apelink"; @@ -2080,7 +2083,8 @@ int main(int argc, char *argv[]) { p = stpcpy(p, " count="); loader->ddarg_size1 = p; p = GenerateDecimalOffsetRelocation(p); - p = stpcpy(p, " bs=1 2>/dev/null | gzip -dc >\"$t.$$\" ||exit\n"); + p = stpcpy( + p, " bs=1 2>/dev/null | /usr/bin/gzip -dc >\"$t.$$\" ||exit\n"); if (loader->macho_offset) { p = stpcpy(p, "/bin/dd if=\"$t.$$\" of=\"$t.$$\""); p = stpcpy(p, " skip="); diff --git a/tool/build/ar.c b/tool/build/ar.c index e006fe655c4..42254669505 100644 --- a/tool/build/ar.c +++ b/tool/build/ar.c @@ -294,7 +294,7 @@ int main(int argc, char *argv[]) { struct ar_hdr header1; struct ar_hdr header2; -#ifndef NDEBUG +#ifdef MODE_DBG ShowCrashReports(); #endif diff --git a/tool/build/compile.c b/tool/build/compile.c index 0382b32d388..973849623b8 100644 --- a/tool/build/compile.c +++ b/tool/build/compile.c @@ -837,7 +837,7 @@ int main(int argc, char *argv[]) { char *s, *q, **envp; int ws, opt, exitcode; -#ifndef NDEBUG +#ifdef MODE_DBG ShowCrashReports(); #endif diff --git a/tool/build/elf2pe.c b/tool/build/elf2pe.c index f640e926f09..849a6cface9 100644 --- a/tool/build/elf2pe.c +++ b/tool/build/elf2pe.c @@ -1078,7 +1078,7 @@ static void Pwrite(int fd, const void *data, size_t size, uint64_t offset) { } int main(int argc, char *argv[]) { -#ifndef NDEBUG +#ifdef MODE_DBG ShowCrashReports(); #endif // get program name diff --git a/tool/build/mkdeps.c b/tool/build/mkdeps.c index f8d1e92bcd3..2507702c48e 100644 --- a/tool/build/mkdeps.c +++ b/tool/build/mkdeps.c @@ -124,6 +124,8 @@ static const uint32_t kSourceExts[] = { EXT("c"), // c EXT("cc"), // c++ EXT("cpp"), // c++ + EXT("cu"), // cuda + EXT("m"), // objective c }; static char *names; @@ -667,7 +669,7 @@ int main(int argc, char *argv[]) { ssize_t rc; size_t i, n; char *makefile; -#ifndef NDEBUG +#ifdef MODE_DBG ShowCrashReports(); #endif prog = argv[0]; diff --git a/tool/build/objbincopy.c b/tool/build/objbincopy.c index ccec6c62fa0..f9e45d52509 100644 --- a/tool/build/objbincopy.c +++ b/tool/build/objbincopy.c @@ -71,7 +71,7 @@ " INPUT is an elf executable made by the unix linker\n" \ "\n" -#ifndef NDEBUG +#ifdef MODE_DBG #define DEBUG(...) kprintf("DEBUG: " __VA_ARGS__) #else #define DEBUG(...) (void)0 diff --git a/tool/build/package.c b/tool/build/package.c index bdf36b19f80..03292bf459c 100644 --- a/tool/build/package.c +++ b/tool/build/package.c @@ -114,7 +114,7 @@ struct Packages { Elf64_Xword symcount; // not persisted int section_offset; int section_count; - } * p; + } *p; } objects; struct Sections { size_t i, n; @@ -128,7 +128,7 @@ struct Packages { kBss, kOther, } kind; - } * p; + } *p; } sections; struct Symbols { size_t i, n; @@ -139,9 +139,9 @@ struct Packages { uint8_t type : 4; uint16_t object; // pkg->objects.p[object] uint16_t section; // pkg->sections.p[section] - } * p; // persisted as pkg+RVA + } *p; // persisted as pkg+RVA } symbols, undefs; // TODO(jart): hash undefs? - } * *p; // persisted across multiple files + } **p; // persisted across multiple files }; struct Relas { @@ -150,7 +150,7 @@ struct Relas { struct Rela { const char *symbol_name; const char *object_path; - } * p; + } *p; } prtu; static wontreturn void Die(const char *path, const char *reason) { @@ -649,7 +649,7 @@ int main(int argc, char *argv[]) { if (argc == 2 && !strcmp(argv[1], "-n")) { exit(0); } -#ifndef NDEBUG +#ifdef MODE_DBG ShowCrashReports(); #endif bzero(&pkg, sizeof(pkg)); diff --git a/tool/build/pecheck.c b/tool/build/pecheck.c index 628a3d8725d..f9fb831c356 100644 --- a/tool/build/pecheck.c +++ b/tool/build/pecheck.c @@ -312,7 +312,7 @@ int main(int argc, char *argv[]) { void *map; ssize_t size; const char *path; -#ifndef NDEBUG +#ifdef MODE_DBG ShowCrashReports(); #endif for (i = 1; i < argc; ++i) { diff --git a/tool/build/runitd.c b/tool/build/runitd.c index c8b971b1599..abae4c4d2f7 100644 --- a/tool/build/runitd.c +++ b/tool/build/runitd.c @@ -809,7 +809,7 @@ int main(int argc, char *argv[]) { if (g_daemonize) Daemonize(); Serve(); free(g_psk); -#if IsModeDbg() +#ifdef MODE_DBG CheckForMemoryLeaks(); CheckForFileLeaks(); #endif diff --git a/tool/build/zipcopy.c b/tool/build/zipcopy.c index a54b66a2c7f..7d50c4e27f8 100644 --- a/tool/build/zipcopy.c +++ b/tool/build/zipcopy.c @@ -211,7 +211,7 @@ static void CopyZip(void) { } int main(int argc, char *argv[]) { -#ifndef NDEBUG +#ifdef MODE_DBG ShowCrashReports(); #endif prog = argv[0]; diff --git a/tool/decode/zip.c b/tool/decode/zip.c index 06306704704..7003aba4940 100644 --- a/tool/decode/zip.c +++ b/tool/decode/zip.c @@ -21,6 +21,7 @@ #include "libc/fmt/libgen.h" #include "libc/fmt/wintime.internal.h" #include "libc/intrin/bits.h" +#include "libc/intrin/kprintf.h" #include "libc/intrin/safemacros.internal.h" #include "libc/log/check.h" #include "libc/log/log.h" @@ -28,6 +29,7 @@ #include "libc/mem/mem.h" #include "libc/nexgen32e/crc32.h" #include "libc/nt/struct/filetime.h" +#include "libc/stdckdint.h" #include "libc/stdio/stdio.h" #include "libc/stdio/sysparam.h" #include "libc/str/str.h" @@ -150,21 +152,71 @@ void ShowExtendedTimestamp(uint8_t *p, size_t n, bool islocal) { } } -void ShowZip64(uint8_t *p, size_t n, bool islocal) { - if (n >= 8) { - show(".quad", _gc(xasprintf("%lu", READ64LE(p))), - _gc(xasprintf("uncompressed size (%,ld)", READ64LE(p)))); +void ShowZip64(uint8_t *lf, uint8_t *p, size_t n, bool islocal) { + int i = 0; + + uint32_t uncompsize; + if (islocal) { + uncompsize = ZIP_LFILE_UNCOMPRESSEDSIZE(lf); + } else { + uncompsize = ZIP_CFILE_UNCOMPRESSEDSIZE(lf); + } + if (uncompsize == 0xffffffffu) { + if (i + 8 <= n) { + show(".quad", _gc(xasprintf("0x%lx", READ64LE(p + i))), + _gc(xasprintf("uncompressed size (%,ld)", READ64LE(p + i)))); + } else { + kprintf("/\tWARNING: ZIP64 EXTRA MISSING UNCOMPRESSED SIZE\n"); + } + i += 8; + } + + uint32_t compsize; + if (islocal) { + compsize = ZIP_LFILE_COMPRESSEDSIZE(lf); + } else { + compsize = ZIP_CFILE_COMPRESSEDSIZE(lf); } - if (n >= 16) { - show(".quad", _gc(xasprintf("%lu", READ64LE(p + 8))), - _gc(xasprintf("compressed size (%,ld)", READ64LE(p + 8)))); + if (compsize == 0xffffffffu) { + if (i + 8 <= n) { + show(".quad", _gc(xasprintf("0x%lx", READ64LE(p + i))), + _gc(xasprintf("compressed size (%,ld)", READ64LE(p + i)))); + } else { + kprintf("/\tWARNING: ZIP64 EXTRA MISSING COMPRESSED SIZE\n"); + } + i += 8; + } + + if (!islocal) { + uint32_t offset; + offset = ZIP_CFILE_OFFSET(lf); + if (offset == 0xffffffffu) { + if (i + 8 <= n) { + show(".quad", _gc(xasprintf("0x%lx", READ64LE(p + i))), + _gc(xasprintf("lfile offset (%,ld)", READ64LE(p + i)))); + } else { + kprintf("/\tWARNING: ZIP64 EXTRA MISSING OFFSET\n"); + } + i += 8; + } } - if (n >= 24) { - show(".quad", _gc(xasprintf("%lu", READ64LE(p + 16))), - _gc(xasprintf("lfile hdr offset (%,ld)", READ64LE(p + 16)))); + + if (!islocal) { + uint16_t disk; + disk = ZIP_CFILE_DISK(lf); + if (disk == 0xffff) { + if (i + 4 <= n) { + show(".long", _gc(xasprintf("0x%x", READ32LE(p + i))), + _gc(xasprintf("lfile disk (%,ld)", READ32LE(p + i)))); + } else { + kprintf("/\tWARNING: ZIP64 EXTRA MISSING DISK\n"); + } + i += 8; + } } - if (n >= 28) { - show(".long", _gc(xasprintf("%u", READ32LE(p + 24))), "disk number"); + + if (i != n) { + kprintf("/\tWARNING: ZIP64 EXTRA HAS SUPERFLUOUS CONTENT\n"); } } @@ -180,7 +232,7 @@ void ShowInfoZipNewUnixExtra(uint8_t *p, size_t n, bool islocal) { } } -void ShowExtra(uint8_t *extra, bool islocal) { +void ShowExtra(uint8_t *lf, uint8_t *extra, bool islocal) { switch (ZIP_EXTRA_HEADERID(extra)) { case kZipExtraNtfs: ShowNtfs(ZIP_EXTRA_CONTENT(extra), ZIP_EXTRA_CONTENTSIZE(extra)); @@ -190,7 +242,7 @@ void ShowExtra(uint8_t *extra, bool islocal) { ZIP_EXTRA_CONTENTSIZE(extra), islocal); break; case kZipExtraZip64: - ShowZip64(ZIP_EXTRA_CONTENT(extra), ZIP_EXTRA_CONTENTSIZE(extra), + ShowZip64(lf, ZIP_EXTRA_CONTENT(extra), ZIP_EXTRA_CONTENTSIZE(extra), islocal); break; case kZipExtraInfoZipNewUnixExtra: @@ -216,7 +268,8 @@ void ShowExternalAttributes(uint8_t *cf) { } } -void ShowExtras(uint8_t *extras, uint16_t extrassize, bool islocal) { +void ShowExtras(uint8_t *lf, uint8_t *extras, uint16_t extrassize, + bool islocal) { int i; bool first; uint8_t *p, *pe; @@ -235,7 +288,7 @@ void ShowExtras(uint8_t *extras, uint16_t extrassize, bool islocal) { first = false; printf("%d:", (i + 1) * 10); } - ShowExtra(p, islocal); + ShowExtra(lf, p, islocal); printf("%d:", (i + 2) * 10); } } @@ -243,8 +296,8 @@ void ShowExtras(uint8_t *extras, uint16_t extrassize, bool islocal) { } void ShowLocalFileHeader(uint8_t *lf, uint16_t idx) { - printf("\n/\t%s #%hu (%zu %s)\n", "local file", idx + 1, - ZIP_LFILE_HDRSIZE(lf), "bytes"); + printf("\n/\t%s #%hu (%zu %s @ %#lx)\n", "local file", idx + 1, + ZIP_LFILE_HDRSIZE(lf), "bytes", lf - map); show(".ascii", format(b1, "%`'.*s", 4, lf), "magic"); show(".byte", firstnonnull(findnamebyid(kZipEraNames, ZIP_LFILE_VERSIONNEED(lf)), @@ -283,7 +336,7 @@ void ShowLocalFileHeader(uint8_t *lf, uint16_t idx) { _gc(strndup(ZIP_LFILE_NAME(lf), ZIP_LFILE_NAMESIZE(lf)))), "name"); printf("1:"); - ShowExtras(ZIP_LFILE_EXTRA(lf), ZIP_LFILE_EXTRASIZE(lf), true); + ShowExtras(lf, ZIP_LFILE_EXTRA(lf), ZIP_LFILE_EXTRASIZE(lf), true); printf("2:"); /* disassemblehex(ZIP_LFILE_CONTENT(lf), ZIP_LFILE_COMPRESSEDSIZE(lf), * stdout); */ @@ -340,7 +393,7 @@ void ShowCentralFileHeader(uint8_t *cf) { if (ZIP_CFILE_OFFSET(cf) == 0xFFFFFFFF) { show(".long", "0xFFFFFFFF", "lfile hdr offset (zip64)"); } else { - show(".long", format(b1, "%u", ZIP_CFILE_OFFSET(cf)), "lfile hdr offset"); + show(".long", format(b1, "0x%x", ZIP_CFILE_OFFSET(cf)), "lfile hdr offset"); } printf("0:"); show(".ascii", @@ -348,7 +401,7 @@ void ShowCentralFileHeader(uint8_t *cf) { _gc(strndup(ZIP_CFILE_NAME(cf), ZIP_CFILE_NAMESIZE(cf)))), "name"); printf("1:"); - ShowExtras(ZIP_CFILE_EXTRA(cf), ZIP_CFILE_EXTRASIZE(cf), false); + ShowExtras(cf, ZIP_CFILE_EXTRA(cf), ZIP_CFILE_EXTRASIZE(cf), false); printf("2:"); show(".ascii", format(b1, "%`'.*s", ZIP_CFILE_COMMENTSIZE(cf), ZIP_CFILE_COMMENT(cf)), @@ -357,8 +410,8 @@ void ShowCentralFileHeader(uint8_t *cf) { } void ShowCentralDirHeader32(uint8_t *cd) { - printf("\n/\t%s (%zu %s)\n", "end of central directory header", - ZIP_CDIR_HDRSIZE(cd), "bytes"); + printf("\n/\t%s (%zu %s @ %#lx)\n", "end of central directory header", + ZIP_CDIR_HDRSIZE(cd), "bytes", cd - map); show(".ascii", format(b1, "%`'.*s", 4, cd), "magic"); show(".short", format(b1, "%hd", ZIP_CDIR_DISK(cd)), "disk"); show(".short", format(b1, "%hd", ZIP_CDIR_STARTINGDISK(cd)), "startingdisk"); @@ -366,7 +419,7 @@ void ShowCentralDirHeader32(uint8_t *cd) { "recordsondisk"); show(".short", format(b1, "%hu", ZIP_CDIR_RECORDS(cd)), "records"); show(".long", format(b1, "%u", ZIP_CDIR_SIZE(cd)), "size"); - show(".long", format(b1, "%u", ZIP_CDIR_OFFSET(cd)), "cfile hdrs offset"); + show(".long", format(b1, "0x%x", ZIP_CDIR_OFFSET(cd)), "cfile hdrs offset"); show(".short", "1f-0f", format(b1, "%s (%hu %s)", "commentsize", ZIP_CDIR_COMMENTSIZE(cd), "bytes")); @@ -376,8 +429,8 @@ void ShowCentralDirHeader32(uint8_t *cd) { } void ShowCentralDirHeader64(uint8_t *cd) { - printf("\n/\t%s (%zu %s)\n", "zip64 end of central directory header", - ZIP_CDIR64_HDRSIZE(cd), "bytes"); + printf("\n/\t%s (%zu %s @ %#lx)\n", "zip64 end of central directory header", + ZIP_CDIR64_HDRSIZE(cd), "bytes", cd - map); show(".ascii", format(b1, "%`'.*s", 4, cd), "magic"); show(".quad", format(b1, "%lu", ZIP_CDIR64_HDRSIZE(cd) - 12), "hdr size"); show(".short", format(b1, "%hd", ZIP_CDIR64_VERSIONMADE(cd)), "version made"); @@ -388,7 +441,7 @@ void ShowCentralDirHeader64(uint8_t *cd) { "recordsondisk"); show(".quad", format(b1, "%lu", ZIP_CDIR64_RECORDS(cd)), "records"); show(".quad", format(b1, "%lu", ZIP_CDIR64_SIZE(cd)), "cdir size"); - show(".quad", format(b1, "%lu", ZIP_CDIR64_OFFSET(cd)), "cdir offset"); + show(".quad", format(b1, "0x%lx", ZIP_CDIR64_OFFSET(cd)), "cdir offset"); printf("0:"); disassemblehex(ZIP_CDIR64_COMMENT(cd), ZIP_CDIR64_COMMENTSIZE(cd), stdout); printf("1:\n"); @@ -397,19 +450,87 @@ void ShowCentralDirHeader64(uint8_t *cd) { kZipCdir64LocatorSize, "bytes"); show(".ascii", format(b1, "%`'.*s", 4, cd), "magic"); show(".long", format(b1, "%d", READ32LE(cd + 4)), "startingdisk"); - show(".quad", format(b1, "%lu", READ64LE(cd + 4 + 4)), "eocd64 offset"); + show(".quad", format(b1, "0x%lx", READ64LE(cd + 4 + 4)), "eocd64 offset"); show(".long", format(b1, "%d", READ32LE(cd + 4 + 4 + 8)), "totaldisks"); } +static const char *DescribeZipError(int err) { + switch (err) { + case kZipErrorEocdNotFound: + return "kZipErrorEocdNotFound"; + case kZipErrorEocdOffsetOverflow: + return "kZipErrorEocdOffsetOverflow"; + case kZipErrorEocdMagicNotFound: + return "kZipErrorEocdMagicNotFound"; + case kZipErrorEocdSizeOverflow: + return "kZipErrorEocdSizeOverflow"; + case kZipErrorEocdDiskMismatch: + return "kZipErrorEocdDiskMismatch"; + case kZipErrorEocdOffsetSizeOverflow: + return "kZipErrorEocdOffsetSizeOverflow"; + case kZipErrorEocdRecordsMismatch: + return "kZipErrorEocdRecordsMismatch"; + case kZipErrorEocdRecordsOverflow: + return "kZipErrorEocdRecordsOverflow"; + case kZipErrorCdirOffsetPastEocd: + return "kZipErrorCdirOffsetPastEocd"; + case kZipErrorEocdLocatorMagic: + return "kZipErrorEocdLocatorMagic"; + case kZipErrorEocdLocatorOffset: + return "kZipErrorEocdLocatorOffset"; + case kZipErrorRaceCondition: + return "kZipErrorRaceCondition"; + case kZipErrorMapFailed: + return "kZipErrorMapFailed"; + case kZipErrorOpenFailed: + return "kZipErrorOpenFailed"; + default: + return "unknown"; + } +} + +int IsZipEocd32(const uint8_t *p, size_t n, size_t i) { + size_t offset; + if (i > n || n - i < kZipCdirHdrMinSize) { + return kZipErrorEocdOffsetOverflow; + } + if (READ32LE(p + i) != kZipCdirHdrMagic) { + return kZipErrorEocdMagicNotFound; + } + if (i + ZIP_CDIR_HDRSIZE(p + i) > n) { + return kZipErrorEocdSizeOverflow; + } + if (ZIP_CDIR_DISK(p + i) != ZIP_CDIR_STARTINGDISK(p + i)) { + return kZipErrorEocdDiskMismatch; + } + if (ZIP_CDIR_RECORDSONDISK(p + i) != ZIP_CDIR_RECORDS(p + i)) { + return kZipErrorEocdRecordsMismatch; + } + if (ZIP_CDIR_RECORDS(p + i) * kZipCfileHdrMinSize > ZIP_CDIR_SIZE(p + i)) { + return kZipErrorEocdRecordsOverflow; + } + if (ckd_add(&offset, ZIP_CDIR_OFFSET(p + i), ZIP_CDIR_SIZE(p + i))) { + return kZipErrorEocdOffsetSizeOverflow; + } + if (offset > i) { + return kZipErrorCdirOffsetPastEocd; + } + return kZipOk; +} + uint8_t *GetZipCdir32(const uint8_t *p, size_t n) { - int64_t i, e; + int64_t i, e, err; if (n >= kZipCdirHdrMinSize) { i = n - kZipCdirHdrMinSize; e = MAX(0, n - 65536); for (; i >= e; --i) { - if (READ32LE(p + i) == kZipCdirHdrMagic && - IsZipEocd32(p, n, i) == kZipOk) { - return (/*unconst*/ uint8_t *)(p + i); + if (READ32LE(p + i) == kZipCdirHdrMagic) { + if ((err = IsZipEocd32(p, n, i)) == kZipOk) { + return (/*unconst*/ uint8_t *)(p + i); + } + kprintf("warning: found eocd32 magic at offset 0x%lx that didn't look " + "like an eocd32 record: %s\n", + i, DescribeZipError(err)); } } } @@ -422,9 +543,13 @@ uint8_t *GetZipCdir64(const uint8_t *p, size_t n) { i = n - kZipCdir64LocatorSize; e = MAX(0, n - 65536); for (; i >= e; --i) { - if (READ32LE(p + i) == kZipCdir64LocatorMagic && - (j = ZIP_LOCATE64_OFFSET(p + i)) + kZipCdir64HdrMinSize <= n) { - return (uint8_t *)p + j; + if (READ32LE(p + i) == kZipCdir64LocatorMagic) { + if ((j = ZIP_LOCATE64_OFFSET(p + i)) + kZipCdir64HdrMinSize <= n) { + CHECK_EQ(kZipCdir64HdrMagic, ZIP_CDIR64_MAGIC((uint8_t *)p + j)); + return (uint8_t *)p + j; + } + kprintf("warning: found eocd64 locator magic that " + "didn't look like an eocd64 locator record\n"); } } }