338 lines
13 KiB
Diff
338 lines
13 KiB
Diff
From b701988480151e6693343ecdb246092824604c61 Mon Sep 17 00:00:00 2001
|
|
From: wangshouping <wangshouping@huawei.com>
|
|
Date: Tue, 11 Feb 2020 19:07:28 -0500
|
|
Subject: [PATCH] add param to limit the number of overlap files
|
|
|
|
Signed-off-by: wangshouping <wangshouping@huawei.com>
|
|
---
|
|
extract.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++--------------
|
|
man/unzip.1 | 8 +++--
|
|
unzip.c | 84 +++++++++++++++++++++++++++++++++++++++-----
|
|
unzip.h | 1 +
|
|
unzip.txt | 6 +++-
|
|
5 files changed, 176 insertions(+), 37 deletions(-)
|
|
|
|
diff --git a/extract.c b/extract.c
|
|
index 3a01d13..031efdb 100644
|
|
--- a/extract.c
|
|
+++ b/extract.c
|
|
@@ -340,23 +340,32 @@ typedef struct {
|
|
span_t *span; /* allocated, distinct, and sorted list of spans */
|
|
size_t num; /* number of spans in the list */
|
|
size_t max; /* allocated number of spans (num <= max) */
|
|
+ unsigned long count;
|
|
} cover_t;
|
|
|
|
/*
|
|
* Return the index of the first span in cover whose beg is greater than val.
|
|
* If there is no such span, then cover->num is returned.
|
|
*/
|
|
-static size_t cover_find(cover, val)
|
|
+static size_t cover_find(cover, val, op)
|
|
cover_t *cover;
|
|
bound_t val;
|
|
+ int op;
|
|
{
|
|
size_t lo = 0, hi = cover->num;
|
|
+ bound_t tmp_val;
|
|
while (lo < hi) {
|
|
size_t mid = (lo + hi) >> 1;
|
|
- if (val < cover->span[mid].beg)
|
|
- hi = mid;
|
|
- else
|
|
- lo = mid + 1;
|
|
+ if (!op) {
|
|
+ tmp_val = cover->span[mid].beg;
|
|
+ } else {
|
|
+ tmp_val = cover->span[mid].end;
|
|
+ }
|
|
+ if (val < tmp_val) {
|
|
+ hi = mid;
|
|
+ } else {
|
|
+ lo = mid + 1;
|
|
+ }
|
|
}
|
|
return hi;
|
|
}
|
|
@@ -366,10 +375,16 @@ static int cover_within(cover, val)
|
|
cover_t *cover;
|
|
bound_t val;
|
|
{
|
|
- size_t pos = cover_find(cover, val);
|
|
+ size_t pos = cover_find(cover, val, 0);
|
|
return pos > 0 && val < cover->span[pos - 1].end;
|
|
}
|
|
|
|
+static int is_exceed_max_overlaps(cover, val)
|
|
+ cover_t *cover;
|
|
+{
|
|
+ return cover->count >= G.UzO.max_overlaps;
|
|
+}
|
|
+
|
|
/*
|
|
* Add a new span to the list, but only if the new span does not overlap any
|
|
* spans already in the list. The new span covers the values beg..end-1. beg
|
|
@@ -387,7 +402,8 @@ static int cover_add(cover, beg, end)
|
|
bound_t beg;
|
|
bound_t end;
|
|
{
|
|
- size_t pos;
|
|
+ size_t pos_beg;
|
|
+ size_t pos_end;
|
|
int prec, foll;
|
|
|
|
if (beg >= end)
|
|
@@ -396,31 +412,76 @@ static int cover_add(cover, beg, end)
|
|
|
|
/* Find where the new span should go, and make sure that it does not
|
|
overlap with any existing spans. */
|
|
- pos = cover_find(cover, beg);
|
|
- if ((pos > 0 && beg < cover->span[pos - 1].end) ||
|
|
- (pos < cover->num && end > cover->span[pos].beg))
|
|
- return 1;
|
|
+ pos_beg = cover_find(cover, beg, 0);
|
|
+ pos_end = cover_find(cover, end, 1);
|
|
|
|
/* Check for adjacencies. */
|
|
- prec = pos > 0 && beg == cover->span[pos - 1].end;
|
|
- foll = pos < cover->num && end == cover->span[pos].beg;
|
|
+ prec = pos_beg > 0 && beg <= cover->span[pos_beg - 1].end;
|
|
+ foll = pos_beg < cover->num && end >= cover->span[pos_beg].beg;
|
|
if (prec && foll) {
|
|
+ if (beg < cover->span[pos_beg - 1].end || end > cover->span[pos_beg].beg) {
|
|
+ cover->count++;
|
|
+ }
|
|
+
|
|
/* The new span connects the preceding and following spans. Merge the
|
|
following span into the preceding span, and delete the following
|
|
span. */
|
|
- cover->span[pos - 1].end = cover->span[pos].end;
|
|
- cover->num--;
|
|
- memmove(cover->span + pos, cover->span + pos + 1,
|
|
- (cover->num - pos) * sizeof(span_t));
|
|
+ if (end <= cover->span[pos_beg].end) {
|
|
+ cover->span[pos_beg - 1].end = cover->span[pos_beg].end;
|
|
+ cover->num--;
|
|
+ memmove(cover->span + pos_beg, cover->span + pos_beg + 1,
|
|
+ (cover->num - pos_beg) * sizeof(span_t));
|
|
+ } else {
|
|
+ if (pos_end == cover->num) {
|
|
+ cover->span[pos_beg - 1].end = end;
|
|
+ cover->num = cover->num - (pos_end - pos_beg);
|
|
+ } else if (end >= cover->span[pos_end].beg) {
|
|
+ cover->span[pos_beg - 1].end = cover->span[pos_end].end;
|
|
+ memmove(cover->span + pos_beg, cover->span + pos_end + 1,
|
|
+ (cover->num - 1 - pos_end) * sizeof(span_t));
|
|
+ cover->num = cover->num - (pos_end - pos_beg) - 1;
|
|
+ } else {
|
|
+ cover->span[pos_beg - 1].end = end;
|
|
+ memmove(cover->span + pos_beg, cover->span + pos_end,
|
|
+ (cover->num - 1 - pos_end + 1) * sizeof(span_t));
|
|
+ cover->num = cover->num - (pos_end - pos_beg);
|
|
+ }
|
|
+ }
|
|
}
|
|
- else if (prec)
|
|
+ else if (prec) {
|
|
/* The new span is adjacent only to the preceding span. Extend the end
|
|
of the preceding span. */
|
|
- cover->span[pos - 1].end = end;
|
|
- else if (foll)
|
|
+ if (beg < cover->span[pos_beg - 1].end) {
|
|
+ cover->count++;
|
|
+ }
|
|
+ if (end > cover->span[pos_beg - 1].end) {
|
|
+ cover->span[pos_beg - 1].end = end;
|
|
+ }
|
|
+ }
|
|
+ else if (foll) {
|
|
+ if (end > cover->span[pos_beg].beg) {
|
|
+ cover->count++;
|
|
+ }
|
|
/* The new span is adjacent only to the following span. Extend the
|
|
beginning of the following span. */
|
|
- cover->span[pos].beg = beg;
|
|
+ cover->span[pos_beg].beg = beg;
|
|
+ if (end > cover->span[pos_beg].end) {
|
|
+ if (pos_end == cover->num) {
|
|
+ cover->span[pos_beg].end = end;
|
|
+ cover->num = cover->num - (pos_end - pos_beg) + 1;
|
|
+ } else if (end >= cover->span[pos_end].beg) {
|
|
+ cover->span[pos_beg].end = cover->span[pos_end].end;
|
|
+ memmove(cover->span + pos_beg + 1, cover->span + pos_end + 1,
|
|
+ (cover->num - 1 - pos_end) * sizeof(span_t));
|
|
+ cover->num = cover->num - (pos_end - pos_beg);
|
|
+ } else {
|
|
+ cover->span[pos_beg].end = end;
|
|
+ memmove(cover->span + pos_beg + 1, cover->span + pos_end,
|
|
+ (cover->num - 1 - pos_end + 1) * sizeof(span_t));
|
|
+ cover->num = cover->num - (pos_end - pos_beg) + 1;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
else {
|
|
/* The new span has gaps between both the preceding and the following
|
|
spans. Assure that there is room and insert the span. */
|
|
@@ -432,11 +493,11 @@ static int cover_add(cover, beg, end)
|
|
cover->span = span;
|
|
cover->max = max;
|
|
}
|
|
- memmove(cover->span + pos + 1, cover->span + pos,
|
|
- (cover->num - pos) * sizeof(span_t));
|
|
+ memmove(cover->span + pos_beg + 1, cover->span + pos_beg,
|
|
+ (cover->num - pos_beg) * sizeof(span_t));
|
|
cover->num++;
|
|
- cover->span[pos].beg = beg;
|
|
- cover->span[pos].end = end;
|
|
+ cover->span[pos_beg].beg = beg;
|
|
+ cover->span[pos_beg].end = end;
|
|
}
|
|
return 0;
|
|
}
|
|
@@ -511,6 +572,7 @@ int extract_or_test_files(__G) /* return PK-type error code */
|
|
((cover_t *)G.cover)->max = 0;
|
|
}
|
|
((cover_t *)G.cover)->num = 0;
|
|
+ ((cover_t *)G.cover)->count = 0;
|
|
if (cover_add((cover_t *)G.cover,
|
|
G.extra_bytes + G.ecrec.offset_start_central_directory,
|
|
G.extra_bytes + G.ecrec.offset_start_central_directory +
|
|
@@ -1218,7 +1280,7 @@ static int extract_or_test_entrylist(__G__ numchunk,
|
|
|
|
/* seek_zipf(__G__ pInfo->offset); */
|
|
request = G.pInfo->offset + G.extra_bytes;
|
|
- if (cover_within((cover_t *)G.cover, request)) {
|
|
+ if (is_exceed_max_overlaps((cover_t *)G.cover)) {
|
|
Info(slide, 0x401, ((char *)slide,
|
|
LoadFarString(OverlappedComponents)));
|
|
return PK_BOMB;
|
|
diff --git a/man/unzip.1 b/man/unzip.1
|
|
index 21816d1..a637a14 100644
|
|
--- a/man/unzip.1
|
|
+++ b/man/unzip.1
|
|
@@ -25,7 +25,7 @@
|
|
unzip \- list, test and extract compressed files in a ZIP archive
|
|
.PD
|
|
.SH SYNOPSIS
|
|
-\fBunzip\fP [\fB\-Z\fP] [\fB\-cflptTuvz\fP[\fBabjnoqsCDKLMUVWX$/:^\fP]]
|
|
+\fBunzip\fP [\fB\-Z\fP] [\fB\-cflptTuvz\fP[\fBabjnoqsCDKLMUVWX$/:^\fP][\fB\-g num\fP]]
|
|
\fIfile\fP[\fI.zip\fP] [\fIfile(s)\fP\ .\|.\|.]
|
|
[\fB\-x\fP\ \fIxfile(s)\fP\ .\|.\|.] [\fB\-d\fP\ \fIexdir\fP]
|
|
.PD
|
|
@@ -195,6 +195,10 @@ but will be in future releases.
|
|
.TP
|
|
.B \-z
|
|
display only the archive comment.
|
|
+.IP \fB\-g\fP\ \fInum\fP
|
|
+limit the number of overlap files. When the number of
|
|
+overlap files exceeds the num we set, it is a bomb. the num
|
|
+is a decimal number.
|
|
.PD
|
|
.\" =========================================================================
|
|
.SH MODIFIERS
|
|
diff --git a/unzip.c b/unzip.c
|
|
index 5b7d288..8c4c37e 100644
|
|
--- a/unzip.c
|
|
+++ b/unzip.c
|
|
@@ -601,7 +601,7 @@ Latest sources and executables are at ftp://ftp.info-zip.org/pub/infozip/ ;\
|
|
\n file[.zip] may be a wildcard. %s\n";
|
|
#else /* !VM_CMS */
|
|
static ZCONST char Far UnzipUsageLine2[] = "\
|
|
-Usage: unzip %s[-opts[modifiers]] file[.zip] [list] [-x xlist] [-d exdir]\n \
|
|
+Usage: unzip %s[-opts[modifiers][-g num]] file[.zip] [list] [-x xlist] [-d exdir]\n \
|
|
Default action is to extract files in list, except those in xlist, to exdir;\n\
|
|
file[.zip] may be a wildcard. %s\n";
|
|
#endif /* ?VM_CMS */
|
|
@@ -647,7 +648,8 @@ static ZCONST char Far UnzipUsageLine3[] = "\n\
|
|
-f freshen existing files, create none -t test compressed archive data\n\
|
|
-u update files, create if necessary -z display archive comment only\n\
|
|
-v list verbosely/show version info %s\n\
|
|
- -x exclude files that follow (in xlist) -d extract files into exdir\n";
|
|
+ -x exclude files that follow (in xlist) -d extract files into exdir\n\
|
|
+ -g limit the number of overlap files\n";
|
|
#endif /* ?VM_CMS */
|
|
#endif /* ?MACOS */
|
|
|
|
@@ -1367,7 +1414,7 @@ int uz_opts(__G__ pargc, pargv)
|
|
extern char OEM_CP[MAX_CP_NAME];
|
|
extern char ISO_CP[MAX_CP_NAME];
|
|
#endif
|
|
-
|
|
+ uO.max_overlaps = (unsigned long)(-1); /* if not set, uncheck overlaps */
|
|
while (++argv, (--argc > 0 && *argv != NULL && **argv == '-')) {
|
|
s = *argv + 1;
|
|
while ((c = *s++) != 0) { /* "!= 0": prevent Turbo C warning */
|
|
@@ -1528,6 +1575,26 @@ int uz_opts(__G__ pargc, pargv)
|
|
uO.acorn_nfs_ext = TRUE;
|
|
break;
|
|
#endif /* RISCOS || ACORN_FTYPE_NFS */
|
|
+#ifdef UNIX
|
|
+ case('g'): /* set overlap entries */
|
|
+ if (negative) { // invalid param, eg: --g
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ "error: invalid param, eg: unzip --g"));
|
|
+ return(PK_PARAM);
|
|
+ } else {
|
|
+ if (argc > 1) {
|
|
+ char *leftover;
|
|
+ --argc;
|
|
+ ++argv;
|
|
+ uO.max_overlaps = strtoul(*argv, &leftover, 10);
|
|
+ } else { /* else pwdarg points at decryption password */
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ "error: invalid param, -g need add decimal number"));
|
|
+ return(PK_PARAM);
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+#endif
|
|
case ('h'): /* just print help message and quit */
|
|
if (showhelp == 0) {
|
|
#ifndef SFX
|
|
@@ -2235,6 +2302,7 @@ static void help_extended(__G)
|
|
" information. Also can be added to other list commands for more",
|
|
" verbose output.",
|
|
" -z Display only archive comment.",
|
|
+ " -g Limit the number of overlap files.",
|
|
"",
|
|
"unzip modifiers:",
|
|
" -a Convert text files to local OS format. Convert line ends, EOF",
|
|
diff --git a/unzip.h b/unzip.h
|
|
index ed24a5b..a7e8a64 100644
|
|
--- a/unzip.h
|
|
+++ b/unzip.h
|
|
@@ -560,6 +560,7 @@ typedef struct _UzpOpts {
|
|
int cflxflag; /* -^: allow control chars in extracted filenames */
|
|
#endif
|
|
#endif /* !FUNZIP */
|
|
+ unsigned long max_overlaps; /* Maximum number of overlaps allowed */
|
|
} UzpOpts;
|
|
|
|
/* intended to be a private struct: */
|
|
diff --git a/unzip.txt b/unzip.txt
|
|
index e8e9719..6594ee6 100644
|
|
--- a/unzip.txt
|
|
+++ b/unzip.txt
|
|
@@ -4,7 +4,7 @@ NAME
|
|
unzip - list, test and extract compressed files in a ZIP archive
|
|
|
|
SYNOPSIS
|
|
- unzip [-Z] [-cflptTuvz[abjnoqsCDKLMUVWX$/:^]] file[.zip] [file(s) ...]
|
|
+ unzip [-Z] [-cflptTuvz[abjnoqsCDKLMUVWX$/:^][-g num]] file[.zip] [file(s) ...]
|
|
[-x xfile(s) ...] [-d exdir]
|
|
|
|
DESCRIPTION
|
|
@@ -177,6 +177,10 @@ OPTIONS
|
|
implemented but will be in future releases.
|
|
|
|
-z display only the archive comment.
|
|
+ -g num
|
|
+ limit the number of overlap files. When the number of overlap f-
|
|
+ iles exceeds the num we set, it is a bomb. the num is a decimal
|
|
+ number.
|
|
|
|
MODIFIERS
|
|
-a convert text files. Ordinarily all files are extracted exactly
|
|
--
|
|
1.8.3.1
|