git: 720785f14ad0 - 2026Q3 - archivers/zip: fix command injection vulnerability

Robert Clausecker <[email protected]>
Newsgroups gmane.os.freebsd.devel.cvs.ports
Message-ID <[email protected]>
The branch 2026Q3 has been updated by fuz:

URL: https://cgit.FreeBSD.org/ports/commit/?id=720785f14ad0d6244f8295885be22f72cbb4e385

commit 720785f14ad0d6244f8295885be22f72cbb4e385
Author:     Robert Clausecker <[email protected]>
AuthorDate: 2026-08-14 09:56:03 +0000
Commit:     Robert Clausecker <[email protected]>
CommitDate: 2026-08-15 19:34:20 +0000

    archivers/zip: fix command injection vulnerability
    
    Insufficient quoting in the -T option gave rise to the possibility of
    a command injection.  Apply a fix from the Debian project.
    
    Reported by:    nimaje (via IRC)
    See also:       https://sintonen.fi/advisories/infozip-test-option-command-injection.txt
    MFH:            2026Q3
    
    (cherry picked from commit 7a7406eab8d872fe5549010305c451e0959db57c)
---
 archivers/zip/Makefile          |   2 +-
 archivers/zip/files/patch-zip.c | 227 +++++++++++++++++++++++++++++++++++++++-
 2 files changed, 224 insertions(+), 5 deletions(-)

diff --git a/archivers/zip/Makefile b/archivers/zip/Makefile
index eb392156abf8..8deeb930dd21 100644
--- a/archivers/zip/Makefile
+++ b/archivers/zip/Makefile
@@ -1,6 +1,6 @@
 PORTNAME=	zip
 PORTVERSION=	3.0
-PORTREVISION=	5
+PORTREVISION=	6
 CATEGORIES=	archivers
 MASTER_SITES=	SF/info${PORTNAME}/Zip%203.x%20%28latest%29/${PORTVERSION}
 DISTNAME=	${PORTNAME}${PORTVERSION:S/.//g}
diff --git a/archivers/zip/files/patch-zip.c b/archivers/zip/files/patch-zip.c
index d81182e3baf1..fb7e7a7e2a03 100644
--- a/archivers/zip/files/patch-zip.c
+++ b/archivers/zip/files/patch-zip.c
@@ -12,9 +12,22 @@ 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 <[email protected]>
+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
-@@ -1028,7 +1028,7 @@ local void help_extended()
+@@ -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++)
    {
@@ -23,7 +36,7 @@ The additional space required in the `cmd` buffer is 4, not 3.
      putchar('\n');
    }
  #ifdef DOS
-@@ -1225,7 +1225,7 @@ local void version_info()
+@@ -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++)
    {
@@ -32,12 +45,218 @@ The additional space required in the `cmd` buffer is 4, not 3.
      putchar('\n');
    }
    ++i;  /* crypt support means there IS at least one compilation option */
-@@ -1437,7 +1437,7 @@ local void check_zipfile(zipname, zippath)
+@@ -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(zipname) + 4)) == 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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.