diff --git a/ChangeLog b/ChangeLog index 2fe1d05..7147925 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,6 @@ +2024-02-29 gdraheim@github + * disabled local file header offset64 + 2024-02-28 gdraheim@github * fixed last cmake bug - parallel builds can lead to race condition * abolished centos8 testbuilds and prepared ubuntu24 diff --git a/zzip/fetch.h b/zzip/fetch.h index 036902d..70d74a3 100644 --- a/zzip/fetch.h +++ b/zzip/fetch.h @@ -286,6 +286,7 @@ __zzip_set64(zzip_byte_t* s, uint64_t v); #define zzip_disk_trailer_to_endoffile(__p) \ ((void*) (zzip_disk_trailer_to_comment(__p) + zzip_disk_trailer_comment(__p))) +#define zzip_use_file_header_zip64_offset 0 #define zzip_extra_zip64_csize(__p) ((zzip_size_t) zzip_extra_zip64_get_csize(__p)) #define zzip_extra_zip64_usize(__p) ((zzip_size_t) zzip_extra_zip64_get_usize(__p)) #define zzip_extra_zip64_offset(__p) ((zzip_off_t) zzip_extra_zip64_get_offset(__p)) diff --git a/zzip/mmapped.c b/zzip/mmapped.c index 13979ea..ab7d679 100644 --- a/zzip/mmapped.c +++ b/zzip/mmapped.c @@ -273,7 +273,7 @@ zzip_disk_entry_to_file_header(ZZIP_DISK* disk, struct zzip_disk_entry* entry) { zzip_byte_t* const ptr = disk->buffer + zzip_disk_entry_fileoffset(entry); zzip_byte_t* const end = ptr + sizeof(struct zzip_file_header); - if (disk->buffer > ptr || end >= disk->endbuf || end <= NULL) { + if (disk->buffer > ptr || end >= disk->endbuf || (void*)end <= NULL) { debug2("file header: offset out of bounds (0x%llx)", (long long unsigned) (disk->buffer)); errno = EBADMSG; return 0; @@ -626,7 +626,7 @@ zzip_disk_entry_fopen(ZZIP_DISK* disk, ZZIP_DISK_ENTRY* entry) ___ /* a ZIP64 extended block may follow. */ size_t csize = zzip_file_header_csize(header); - off_t offset = zzip_file_header_to_data(header); + zzip_byte_t* start = zzip_file_header_to_data(header); if (csize == 0xFFFFu) { struct zzip_extra_zip64* zip64 = (struct zzip_extra_zip64*) zzip_file_header_to_extras(header); @@ -634,11 +634,29 @@ zzip_disk_entry_fopen(ZZIP_DISK* disk, ZZIP_DISK_ENTRY* entry) csize = zzip_extra_zip64_csize(zip64); } } - if (offset == 0xFFFFu) { + + if (((unsigned long)start) & 0xFFFFu == 0xFFFFu) { + /* actually the ZIP64 rootseek in the central directory should have updated the + header start with the data portion to follow right behind it. The usage of + this field in a local file header is wrong on a number of levels. Specifically + that the zip64 extended field value points to yet another header but it is + actually used to point to the actual data portion instead. */ struct zzip_extra_zip64* zip64 = (struct zzip_extra_zip64*) zzip_file_header_to_extras(header); if (ZZIP_EXTRA_ZIP64_CHECK(zip64)) { - offset = zzip_extra_zip64_offset(zip64); + zzip_off64_t offset = zzip_extra_zip64_offset(zip64); /* offset of local header record */ + if (offset && zzip_use_file_header_zip64_offset) { + start = disk->buffer + offset; /* but points directly to the data portion */ + if (disk->buffer > start || start+csize >= disk->endbuf) { + debug2("file start: offset out of bounds (0x%llx)", (long long unsigned) (offset)); + errno = EBADMSG; + return 0; + } + } else { + debug1("file start: no zip64 local offset"); + errno = EBADMSG; + return 0; + } } } @@ -647,7 +665,7 @@ zzip_disk_entry_fopen(ZZIP_DISK* disk, ZZIP_DISK_ENTRY* entry) file->zlib.zalloc = Z_NULL; file->zlib.zfree = Z_NULL; file->zlib.avail_in = csize; - file->zlib.next_in = offset; + file->zlib.next_in = start; ____; DBG2("compressed size %i", (int) file->zlib.avail_in);