From 47ef6834c594b1f53650b3e3e3a374ed5483517e Mon Sep 17 00:00:00 2001 From: Robert Pengelly Date: Wed, 1 Oct 2025 15:45:41 +0100 Subject: [PATCH] Don't assume that Local File Header is valid --- unzip.c | 98 ++++++++++++--------------------------------------------- unzip.h | 2 +- 2 files changed, 21 insertions(+), 79 deletions(-) diff --git a/unzip.c b/unzip.c index 20c684d..056bc88 100755 --- a/unzip.c +++ b/unzip.c @@ -287,9 +287,9 @@ static int read_cfh (struct cfh *cfh) { } - if ((cfh->extra = malloc (cfh->extra_len + 1))) { + if ((cfh->extra = malloc (cfh->extra_len))) { - memset (cfh->extra, 0, cfh->extra_len + 1); + memset (cfh->extra, 0, cfh->extra_len); if (fread (cfh->extra, 1, cfh->extra_len, fp) != cfh->extra_len) { @@ -577,52 +577,6 @@ static int read_lfh (struct lfh *lfh) { } -static int validate_structs (struct cfh *cfh, struct lfh *lfh) { - - if (cfh->extract_ver != lfh->extract_ver) { - return -1; - } - - if (cfh->gp_flag != lfh->gp_flag) { - return -1; - } - - if (cfh->method != lfh->method) { - return -1; - } - - if (cfh->mod_date != lfh->mod_date) { - return -1; - } - - if (cfh->mod_time != lfh->mod_time) { - return -1; - } - - if (cfh->crc32 != lfh->crc32) { - return -1; - } - - if (cfh->comp_size != lfh->comp_size) { - return -1; - } - - if (cfh->uncomp_size != lfh->uncomp_size) { - return -1; - } - - if (cfh->name_len != lfh->name_len) { - return -1; - } - - if (!lfh->name || strcmp (lfh->name, cfh->name)) { - return -1; - } - - return 0; - -} - static void extract_zip (const char *path) { struct eocdr eocdr = { 0 }; @@ -737,7 +691,7 @@ static void extract_zip (const char *path) { } - if (cfh.ext_attrs & EXT_ATTR_DIR) { + if (cfh.ext_attrs & EXT_ATTR_DIR || cfh.name[cfh.name_len - 1] == '/') { if (state->exdir) { @@ -779,19 +733,19 @@ static void extract_zip (const char *path) { } sprintf (temp, "%s", cfh.name); - - } - - if (!is_relative (temp, cfh.name_len)) { - - free (temp); - free (cfh.name); - if (cfh.comment) { free (cfh.comment); } - if (cfh.extra) { free (cfh.extra); } + if (!is_relative (temp, cfh.name_len)) { + + free (temp); + free (cfh.name); + + if (cfh.comment) { free (cfh.comment); } + if (cfh.extra) { free (cfh.extra); } + + memset (&cfh, 0, sizeof (cfh)); + continue; - memset (&cfh, 0, sizeof (cfh)); - continue; + } } @@ -922,17 +876,6 @@ static void extract_zip (const char *path) { } - if (validate_structs (&cfh, &lfh)) { - - report_at (program_name, 0, REPORT_ERROR, "Centeral File Header and Local File Header mismatch"); - - fseek (fp, orig_offset, SEEK_SET); - free (temp); - - break; - - } - if (!(data = malloc (cfh.comp_size))) { fseek (fp, orig_offset, SEEK_SET); @@ -942,7 +885,7 @@ static void extract_zip (const char *path) { } - if (fread (data, 1, lfh.comp_size, fp) != lfh.comp_size) { + if (fread (data, 1, cfh.comp_size, fp) != cfh.comp_size) { fseek (fp, orig_offset, SEEK_SET); @@ -964,7 +907,7 @@ static void extract_zip (const char *path) { if (cfh.method == ZIP_STORE) { - assert (lfh.comp_size == lfh.uncomp_size); + assert (cfh.comp_size == cfh.uncomp_size); if (!(outfile = fopen (temp, "w+b"))) { @@ -978,7 +921,7 @@ static void extract_zip (const char *path) { } - if (fwrite (data, 1, lfh.uncomp_size, outfile) != lfh.uncomp_size) { + if (fwrite (data, 1, cfh.uncomp_size, outfile) != cfh.uncomp_size) { report_at (program_name, 0, REPORT_ERROR, "failed to extract %s", temp); fclose (outfile); @@ -1009,7 +952,7 @@ static void extract_zip (const char *path) { printf (" inflating: %s\n", temp); - if (hwinflate (data, lfh.comp_size, &src_used, outfile, lfh.uncomp_size, &dst_used) != HWINF_OK) { + if (hwinflate (data, cfh.comp_size, &src_used, outfile, cfh.uncomp_size, &dst_used) != HWINF_OK) { report_at (program_name, 0, REPORT_ERROR, "failed to extract %s", temp); fclose (outfile); @@ -1024,10 +967,9 @@ static void extract_zip (const char *path) { free (data); fclose (outfile); - if (src_used != lfh.comp_size || dst_used != lfh.uncomp_size) { + if (src_used != cfh.comp_size || dst_used != cfh.uncomp_size) { - report_at (program_name, 0, REPORT_ERROR, "%lld, %d, %lld, %d: failed to extract %s", - src_used, lfh.comp_size, dst_used, lfh.uncomp_size, temp); + report_at (program_name, 0, REPORT_ERROR, "failed to extract %s", temp); remove (temp); break; diff --git a/unzip.h b/unzip.h index ee4bdd0..e1757f8 100755 --- a/unzip.h +++ b/unzip.h @@ -23,7 +23,7 @@ extern struct unzip_state *state; extern const char *program_name; #define EXT_ATTR_DIR (1U << 4) -#define EXT_ATTR_ARC (1U << 5); +#define EXT_ATTR_ARC (1U << 5) #define ZIP_STORE 0 #define ZIP_DEFLATE 8 -- 2.34.1