123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113 |
- From 6d351831be705cc26d897db44f878a978f4138fc Mon Sep 17 00:00:00 2001
- From: Mark Adler <madler@alumni.caltech.edu>
- Date: Thu, 25 Jul 2019 20:43:17 -0700
- Subject: [PATCH] Do not raise a zip bomb alert for a misplaced central
- directory.
- There is a zip-like file in the Firefox distribution, omni.ja,
- which is a zip container with the central directory placed at the
- start of the file instead of after the local entries as required
- by the zip standard. This commit marks the actual location of the
- central directory, as well as the end of central directory records,
- as disallowed locations. This now permits such containers to not
- raise a zip bomb alert, where in fact there are no overlaps.
- ---
- extract.c | 25 +++++++++++++++++++------
- process.c | 6 ++++++
- unzpriv.h | 10 ++++++++++
- 3 files changed, 35 insertions(+), 6 deletions(-)
- diff --git a/extract.c b/extract.c
- index 0973a33..1b73cb0 100644
- --- a/extract.c
- +++ b/extract.c
- @@ -493,8 +493,11 @@ int extract_or_test_files(__G) /* return PK-type error code */
- }
- #endif /* !SFX || SFX_EXDIR */
-
- - /* One more: initialize cover structure for bomb detection. Start with a
- - span that covers the central directory though the end of the file. */
- + /* One more: initialize cover structure for bomb detection. Start with
- + spans that cover any extra bytes at the start, the central directory,
- + the end of central directory record (including the Zip64 end of central
- + directory locator, if present), and the Zip64 end of central directory
- + record, if present. */
- if (G.cover == NULL) {
- G.cover = malloc(sizeof(cover_t));
- if (G.cover == NULL) {
- @@ -506,15 +509,25 @@ int extract_or_test_files(__G) /* return PK-type error code */
- ((cover_t *)G.cover)->max = 0;
- }
- ((cover_t *)G.cover)->num = 0;
- - if ((G.extra_bytes != 0 &&
- - cover_add((cover_t *)G.cover, 0, G.extra_bytes) != 0) ||
- - cover_add((cover_t *)G.cover,
- + if (cover_add((cover_t *)G.cover,
- G.extra_bytes + G.ecrec.offset_start_central_directory,
- - G.ziplen) != 0) {
- + G.extra_bytes + G.ecrec.offset_start_central_directory +
- + G.ecrec.size_central_directory) != 0) {
- Info(slide, 0x401, ((char *)slide,
- LoadFarString(NotEnoughMemCover)));
- return PK_MEM;
- }
- + if ((G.extra_bytes != 0 &&
- + cover_add((cover_t *)G.cover, 0, G.extra_bytes) != 0) ||
- + (G.ecrec.have_ecr64 &&
- + cover_add((cover_t *)G.cover, G.ecrec.ec64_start,
- + G.ecrec.ec64_end) != 0) ||
- + cover_add((cover_t *)G.cover, G.ecrec.ec_start,
- + G.ecrec.ec_end) != 0) {
- + Info(slide, 0x401, ((char *)slide,
- + LoadFarString(OverlappedComponents)));
- + return PK_BOMB;
- + }
-
- /*---------------------------------------------------------------------------
- The basic idea of this function is as follows. Since the central di-
- diff --git a/process.c b/process.c
- index d2e4dc3..d75d405 100644
- --- a/process.c
- +++ b/process.c
- @@ -1408,6 +1408,10 @@ static int find_ecrec64(__G__ searchlen) /* return PK-class error */
-
- /* Now, we are (almost) sure that we have a Zip64 archive. */
- G.ecrec.have_ecr64 = 1;
- + G.ecrec.ec_start -= ECLOC64_SIZE+4;
- + G.ecrec.ec64_start = ecrec64_start_offset;
- + G.ecrec.ec64_end = ecrec64_start_offset +
- + 12 + makeint64(&byterec[ECREC64_LENGTH]);
-
- /* Update the "end-of-central-dir offset" for later checks. */
- G.real_ecrec_offset = ecrec64_start_offset;
- @@ -1542,6 +1546,8 @@ static int find_ecrec(__G__ searchlen) /* return PK-class error */
- makelong(&byterec[OFFSET_START_CENTRAL_DIRECTORY]);
- G.ecrec.zipfile_comment_length =
- makeword(&byterec[ZIPFILE_COMMENT_LENGTH]);
- + G.ecrec.ec_start = G.real_ecrec_offset;
- + G.ecrec.ec_end = G.ecrec.ec_start + 22 + G.ecrec.zipfile_comment_length;
-
- /* Now, we have to read the archive comment, BEFORE the file pointer
- is moved away backwards to seek for a Zip64 ECLOC64 structure.
- diff --git a/unzpriv.h b/unzpriv.h
- index dc9eff5..297b3c7 100644
- --- a/unzpriv.h
- +++ b/unzpriv.h
- @@ -2185,6 +2185,16 @@ typedef struct VMStimbuf {
- int have_ecr64; /* valid Zip64 ecdir-record exists */
- int is_zip64_archive; /* Zip64 ecdir-record is mandatory */
- ush zipfile_comment_length;
- + zusz_t ec_start, ec_end; /* offsets of start and end of the
- + end of central directory record,
- + including if present the Zip64
- + end of central directory locator,
- + which immediately precedes the
- + end of central directory record */
- + zusz_t ec64_start, ec64_end; /* if have_ecr64 is true, then these
- + are the offsets of the start and
- + end of the Zip64 end of central
- + directory record */
- } ecdir_rec;
-
-
|