Files
2026-10-04 04:07:15 +00:00

263 lines
7.8 KiB
C

From: Santiago Vila <sanvila@debian.org>
Subject: Use format specifier %s to print strings, not the string itself
Bug-Debian: https://bugs.debian.org/673476
X-Debian-version: 3.0-5
From: Florent 'Skia' Jacquet <florent.jacquet@canonical.com>
Subject: Fix buffer overflow when using '-T -TT'
Bug-Debian: https://bugs.debian.org/1093629
Bug-Ubuntu: https://launchpad.net/bugs/2093024
Forwarded: https://sourceforge.net/p/infozip/bugs/81/
strlen(unzip_path) + strlen(zipname) + " " + "'" + "'" + '\0'
The additional space required in the `cmd` buffer is 4, not 3.
From: Paul Marquess <pmqs@outlook.com>
Subject: Fix command injection issue
Bug-Debian: https://bugs.debian.org/1143866
X-Debian-version: 3.0-16
--- zip.c.orig 2008-07-05 16:34:06 UTC
+++ zip.c
@@ -122,6 +122,7 @@ local int finish OF((int));
local void freeup OF((void));
local int finish OF((int));
+local char *quote_arg(char *instring);
#if (!defined(MACOS) && !defined(WINDLL))
local void handler OF((int));
local void license OF((void));
@@ -1028,7 +1029,7 @@ local void help_extended()
for (i = 0; i < sizeof(text)/sizeof(char *); i++)
{
- printf(text[i]);
+ printf("%s", text[i]);
putchar('\n');
}
#ifdef DOS
@@ -1225,7 +1226,7 @@ local void version_info()
CR_MAJORVER, CR_MINORVER, CR_BETA_VER, CR_VERSION_DATE);
for (i = 0; i < sizeof(cryptnote)/sizeof(char *); i++)
{
- printf(cryptnote[i]);
+ printf("%s", cryptnote[i]);
putchar('\n');
}
++i; /* crypt support means there IS at least one compilation option */
@@ -1323,6 +1324,134 @@ local int check_unzip_version(unzippath)
return 1;
}
+
+/* quote_arg()
+ *
+ * Add quotation and/or escapes to a shell (VMS: DCL) argument string
+ * appropriate to the local operating system or shell (Unix, Windows,
+ * etc.). This is mainly used to build the command line to pass to
+ * UnZip (or other application when -TT used) to test an archive.
+ * Return malloc()'d result.
+ *
+ * All: Add " at beginning and end.
+ * MSDOS: % -> "^%"
+ * " -> \""
+ * Unix: ! -> "'!'"
+ * $ -> \$
+ * \ -> \\
+ * ` -> \`
+ * Non-VMS: " -> \"
+ * VMS: " -> """
+ *
+ * On VMS, quoted double apostrophes are also special. Currently not
+ * handled. (How? Quotation marks are needed for (upper-)case
+ * preservation. Double apostrophes in quotation marks are interpreted
+ * (symbol evaluation). SMS sees no way to handle "fr''ed". "fr'""'ed"
+ * becomes >fr'"'ed<, for example.) Not a problem for file specs, but
+ * imposes a restriction on passwords.
+ */
+#ifndef NO_PROTO
+local char *quote_arg(char *instring)
+#else
+local char *quote_arg(instring)
+ char *instring;
+#endif
+{
+ int i;
+ int j;
+ char *tempstring;
+ char *outstring;
+ char c;
+
+ if (instring == NULL)
+ return NULL;
+
+# ifdef MSDOS
+# define QA_FACTOR 4 /* Worst case (MSDOS): % -> "^%" */
+
+# else /* not MSDOS */
+# ifdef VMS
+# define QA_FACTOR 3 /* Worst case (VMS): " -> """ */
+
+# else /* not MSDOS or VMS */
+# define QA_FACTOR 5 /* Worst case (Unix): ! -> "'!'" */
+# endif /* VMS [else] */
+# endif /* MSDOS [else] */
+
+# define QA_INCR 2 /* Surrounding quotation marks. */
+
+ i = QA_FACTOR * (int)strlen(instring) + QA_INCR + 1;
+ if ((tempstring = (char *)malloc(i)) == NULL) {
+ ZIPERR(ZE_MEM, "quote_arg");
+ }
+
+ j = 0;
+
+ tempstring[j++] = '\"'; /* Surrounding quotation mark (start). */
+
+ for (i = 0; instring[i]; i++) {
+ c = instring[i];
+
+# ifdef MSDOS /* or Windows */
+ if (c == '%') /* Percent. */
+ {
+ tempstring[j++] = '"'; /* Add (closing) quotation mark. */
+ tempstring[j++] = '^'; /* Add caret escape. */
+ tempstring[j++] = '%'; /* Original character (%). */
+ c = '"'; /* Prepare (re-opening) quotation mark. */
+ }
+ else if (c == '"') /* Quotation mark. */
+ {
+ tempstring[j++] = '\\'; /* Add backslash (escape). */
+ tempstring[j++] = '"'; /* Add quote (acts as closing and literal). */
+ }
+# else /* not def MSDOS */
+
+# ifdef VMS
+ if (c == '"') /* Quotation mark. */
+ {
+ tempstring[j++] = '"'; /* Add two quotation marks. */
+ tempstring[j++] = '"';
+ }
+# else /* not def VMS */
+
+ /* UNIX is default for others */
+
+ if (c == '"') /* Quotation mark. */
+ {
+ tempstring[j++] = '\\'; /* Add backslash (escape). */
+ }
+ else if (c == '!') /* Exclamation. (Inefficient.) */
+ {
+ tempstring[j++] = '"'; /* Add (closing) quotation mark. */
+ tempstring[j++] = '\''; /* Add (opening) apostrophe. */
+ tempstring[j++] = '!'; /* Original character (!). */
+ tempstring[j++] = '\''; /* Add (closing) apostrophe. */
+ c = '"'; /* Prepare (re-opening) quotation mark. */
+ }
+ else if ((c == '$') || /* Dollar sign. */
+ (c == '`') || /* Grave accent (backtick). */
+ (c == '\\')) /* Backslash. */
+ {
+ tempstring[j++] = '\\'; /* Add backslash (escape). */
+ }
+
+# endif /* def VMS [else] */
+# endif /* def MSDOS [else] */
+
+ tempstring[j++] = c; /* Original (or other last) character. */
+ }
+
+ tempstring[j++] = '\"'; /* Surrounding quotation mark (end). */
+
+ tempstring[j] = '\0';
+ /* outstring = string_dup(tempstring, "quote_arg", NO_FLUFF); */
+ outstring = strdup(tempstring);
+ free(tempstring);
+
+ return outstring;
+}
+
local void check_zipfile(zipname, zippath)
char *zipname;
char *zippath;
@@ -1424,11 +1553,15 @@ local void check_zipfile(zipname, zippath)
#else /* (MSDOS && !__GO32__) || __human68k__ */
char *cmd;
+ char *qzipname;
int result;
/* Tell picky compilers to shut up about unused variables */
zippath = zippath;
+ /* Quote each arg (and add appropriate escapes). */
+ qzipname = quote_arg(zipname);
+
if (unzip_path) {
/* user gave us a path to some unzip (may not be UnZip) */
char *here;
@@ -1437,7 +1570,7 @@ local void check_zipfile(zipname, zippath)
/* Replace first {} with archive name. If no {} append name to string. */
here = strstr(unzip_path, "{}");
- if ((cmd = malloc(strlen(unzip_path) + strlen(zipname) + 3)) == NULL) {
+ if ((cmd = malloc(strlen(unzip_path) + strlen(qzipname) + 4)) == NULL) {
ziperr(ZE_MEM, "building command string for testing archive");
}
@@ -1447,32 +1580,20 @@ local void check_zipfile(zipname, zippath)
strcpy(cmd, unzip_path);
cmd[len] = '\0';
strcat(cmd, " ");
-# ifdef UNIX
- strcat(cmd, "'"); /* accept space or $ in name */
- strcat(cmd, zipname);
- strcat(cmd, "'");
-# else
- strcat(cmd, zipname);
-# endif
+ strcat(cmd, qzipname);
strcat(cmd, " ");
strcat(cmd, here + 2);
} else {
/* No {} so append temp name to end */
strcpy(cmd, unzip_path);
strcat(cmd, " ");
-# ifdef UNIX
- strcat(cmd, "'"); /* accept space or $ in name */
- strcat(cmd, zipname);
- strcat(cmd, "'");
-# else
- strcat(cmd, zipname);
-# endif
+ strcat(cmd, qzipname);
}
free(unzip_path);
unzip_path = NULL;
} else {
- if ((cmd = malloc(20 + strlen(zipname))) == NULL) {
+ if ((cmd = malloc(20 + strlen(qzipname))) == NULL) {
ziperr(ZE_MEM, "building command string for testing archive");
}
@@ -1484,14 +1605,11 @@ local void check_zipfile(zipname, zippath)
if (check_unzip_version("unzip") == 0)
ZIPERR(ZE_TEST, zipfile);
-# ifdef UNIX
- strcat(cmd, "'"); /* accept space or $ in name */
- strcat(cmd, zipname);
- strcat(cmd, "'");
-# else
- strcat(cmd, zipname);
-# endif
+ strcat(cmd, qzipname);
}
+
+ if (qzipname)
+ free(qzipname);
result = system(cmd);
# ifdef VMS