From: Russell Mullens Date: Sat, 20 Mar 2021 07:59:12 +0000 (+1100) Subject: Calculate where the Central Directory is based on the size of the Central Directory... X-Git-Tag: v3.5.2~25^2~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f5da47515fdd42153cb0c2da1b2b93fb87f67915;p=thirdparty%2Flibarchive.git Calculate where the Central Directory is based on the size of the Central Directory in EOCD and where the OECD was found. This prevents large reads when a zip archive is preceded by other data. --- diff --git a/libarchive/archive_read_support_format_zip.c b/libarchive/archive_read_support_format_zip.c index a64332c28..d7f318f80 100644 --- a/libarchive/archive_read_support_format_zip.c +++ b/libarchive/archive_read_support_format_zip.c @@ -142,6 +142,7 @@ struct zip { /* Structural information about the archive. */ struct archive_string format_name; int64_t central_directory_offset; + int64_t central_directory_offset_actual; size_t central_directory_entries_total; size_t central_directory_entries_on_this_disk; int has_encrypted_entries; @@ -3433,6 +3434,8 @@ read_eocd(struct zip *zip, const char *p, int64_t current_offset) /* Save the central directory location for later use. */ zip->central_directory_offset = archive_le32dec(p + 16); + zip->central_directory_offset_actual = current_offset + - archive_le32dec(p+12) - 1; /* This is just a tiny bit higher than the maximum returned by the streaming Zip bidder. This ensures @@ -3484,6 +3487,7 @@ read_zip64_eocd(struct archive_read *a, struct zip *zip, const char *p) /* Save the central directory offset for later use. */ zip->central_directory_offset = archive_le64dec(p + 48); + zip->central_directory_offset_actual = zip->central_directory_offset; return 32; } @@ -3655,7 +3659,8 @@ slurp_central_directory(struct archive_read *a, struct archive_entry* entry, * know the correction we need to apply to account for leading * padding. */ - if (__archive_read_seek(a, zip->central_directory_offset, SEEK_SET) < 0) + if (__archive_read_seek(a, zip->central_directory_offset_actual, SEEK_SET) + < 0) return ARCHIVE_FATAL; found = 0;