master hovercats/oakiss / pkg / unzip / patch / 0028-Fix-for-CVE-2022-0529-and-CVE-2022-0530.patch
  1From 7c5862de85894d5387c855b5df6e5509c97f5bdf Mon Sep 17 00:00:00 2001
  2From: "Steven M. Schweda" <sms@antinode.info>
  3Date: Mon, 28 Apr 2025 12:57:34 -0700
  4Subject: [PATCH] Fix for CVE-2022-0529 and CVE-2022-0530
  5
  6---
  7 fileio.c  | 34 +++++++++++++++++++++++++---------
  8 process.c | 55 ++++++++++++++++++++++++++++++++++++++++++++-----------
  9 2 files changed, 69 insertions(+), 20 deletions(-)
 10
 11diff --git a/fileio.c b/fileio.c
 12index 6290824..50a74fc 100644
 13--- a/fileio.c
 14+++ b/fileio.c
 15@@ -171,8 +171,10 @@ static ZCONST char Far ReadError[] = "error:  zipfile read error\n";
 16 static ZCONST char Far FilenameTooLongTrunc[] =
 17   "warning:  filename too long--truncating.\n";
 18 #ifdef UNICODE_SUPPORT
 19+   static ZCONST char Far UFilenameCorrupt[] =
 20+     "error: Unicode filename corrupt.\n";
 21    static ZCONST char Far UFilenameTooLongTrunc[] =
 22-     "warning:  Converted unicode filename too long--truncating.\n";
 23+     "warning:  Converted Unicode filename too long--truncating.\n";
 24 #endif
 25 static ZCONST char Far ExtraFieldTooLong[] =
 26   "warning:  extra field too long (%d).  Ignoring...\n";
 27@@ -2361,16 +2363,30 @@ int do_string(__G__ length, option)   /* return PK-type error code */
 28                   /* convert UTF-8 to local character set */
 29                   fn = utf8_to_local_string(G.unipath_filename,
 30                                             G.unicode_escape_all);
 31-                  /* make sure filename is short enough */
 32-                  if (strlen(fn) >= FILNAMSIZ) {
 33-                    fn[FILNAMSIZ - 1] = '\0';
 34+
 35+                  /* 2022-07-22 SMS, et al.  CVE-2022-0530
 36+                   * Detect conversion failure, emit message.
 37+                   * Continue with unconverted name.
 38+                   */
 39+                  if (fn == NULL)
 40+                  {
 41                     Info(slide, 0x401, ((char *)slide,
 42-                      LoadFarString(UFilenameTooLongTrunc)));
 43-                    error = PK_WARN;
 44+                     LoadFarString(UFilenameCorrupt)));
 45+                    error = PK_ERR;
 46+                  }
 47+                  else
 48+                  {
 49+                    /* make sure filename is short enough */
 50+                    if (strlen(fn) >= FILNAMSIZ) {
 51+                      fn[FILNAMSIZ - 1] = '\0';
 52+                      Info(slide, 0x401, ((char *)slide,
 53+                        LoadFarString(UFilenameTooLongTrunc)));
 54+                      error = PK_WARN;
 55+                    }
 56+                    /* replace filename with converted UTF-8 */
 57+                    strcpy(G.filename, fn);
 58+                    free(fn);
 59                   }
 60-                  /* replace filename with converted UTF-8 */
 61-                  strcpy(G.filename, fn);
 62-                  free(fn);
 63                 }
 64 # endif /* UNICODE_WCHAR */
 65                 if (G.unipath_filename != G.filename_full)
 66diff --git a/process.c b/process.c
 67index d2a846e..a7d5b87 100644
 68--- a/process.c
 69+++ b/process.c
 70@@ -222,6 +222,8 @@ static ZCONST char Far ZipfileCommTrunc1[] =
 71      "\nwarning:  Unicode Path version > 1\n";
 72    static ZCONST char Far UnicodeMismatchError[] =
 73      "\nwarning:  Unicode Path checksum invalid\n";
 74+   static ZCONST char Far UFilenameTooLongTrunc[] =
 75+     "warning:  filename too long (P1) -- truncating.\n";
 76 #endif
 77 
 78 
 79@@ -1915,7 +1917,7 @@ int getZip64Data(__G__ ef_buf, ef_len)
 80     Sets both local header and central header fields.  Not terribly clever,
 81     but it means that this procedure is only called in one place.
 82 
 83-    2014-12-05 SMS.
 84+    2014-12-05 SMS.  (oCERT.org report.)  CVE-2014-8141.
 85     Added checks to ensure that enough data are available before calling
 86     makeint64() or makelong().  Replaced various sizeof() values with
 87     simple ("4" or "8") constants.  (The Zip64 structures do not depend
 88@@ -1947,9 +1949,10 @@ int getZip64Data(__G__ ef_buf, ef_len)
 89               ef_len - EB_HEADSIZE));
 90             break;
 91         }
 92+
 93         if (eb_id == EF_PKSZ64)
 94         {
 95-          int offset = EB_HEADSIZE;
 96+          unsigned offset = EB_HEADSIZE;
 97 
 98           if ((G.crec.ucsize == Z64FLGL) || (G.lrec.ucsize == Z64FLGL))
 99           {
100@@ -2046,7 +2049,7 @@ int getUnicodeData(__G__ ef_buf, ef_len)
101         }
102         if (eb_id == EF_UNIPATH) {
103 
104-          int offset = EB_HEADSIZE;
105+          unsigned offset = EB_HEADSIZE;
106           ush ULen = eb_len - 5;
107           ulg chksum = CRCVAL_INITIAL;
108 
109@@ -2504,16 +2507,17 @@ char *wide_to_local_string(wide_string, escape_all)
110   int state_dependent;
111   int wsize = 0;
112   int max_bytes = MB_CUR_MAX;
113-  char buf[9];
114+  char buf[ MB_CUR_MAX+ 1];             /* ("+1" not really needed?) */
115   char *buffer = NULL;
116   char *local_string = NULL;
117+  size_t buffer_size;                   /* CVE-2022-0529 */
118 
119   for (wsize = 0; wide_string[wsize]; wsize++) ;
120 
121   if (max_bytes < MAX_ESCAPE_BYTES)
122     max_bytes = MAX_ESCAPE_BYTES;
123-
124-  if ((buffer = (char *)malloc(wsize * max_bytes + 1)) == NULL) {
125+  buffer_size = wsize * max_bytes + 1;          /* Reused below. */
126+  if ((buffer = (char *)malloc( buffer_size)) == NULL) {
127     return NULL;
128   }
129 
130@@ -2551,8 +2555,28 @@ char *wide_to_local_string(wide_string, escape_all)
131     } else {
132       /* no MB for this wide */
133         /* use escape for wide character */
134-        char *escape_string = wide_to_escape_string(wide_string[i]);
135-        strcat(buffer, escape_string);
136+        size_t buffer_len;
137+        size_t escape_string_len;
138+        char *escape_string;
139+        int err_msg = 0;
140+
141+        escape_string = wide_to_escape_string(wide_string[i]);
142+        buffer_len = strlen( buffer);
143+        escape_string_len = strlen( escape_string);
144+
145+        /* Append escape string, as space allows. */
146+        /* 2022-07-18 SMS, et al.  CVE-2022-0529 */
147+        if (escape_string_len > buffer_size- buffer_len- 1)
148+        {
149+            escape_string_len = buffer_size- buffer_len- 1;
150+            if (err_msg == 0)
151+            {
152+                err_msg = 1;
153+                Info(slide, 0x401, ((char *)slide,
154+                 LoadFarString( UFilenameTooLongTrunc)));
155+            }
156+        }
157+        strncat( buffer, escape_string, escape_string_len);
158         free(escape_string);
159     }
160   }
161@@ -2604,9 +2628,18 @@ char *utf8_to_local_string(utf8_string, escape_all)
162   ZCONST char *utf8_string;
163   int escape_all;
164 {
165-  zwchar *wide = utf8_to_wide_string(utf8_string);
166-  char *loc = wide_to_local_string(wide, escape_all);
167-  free(wide);
168+  zwchar *wide;
169+  char *loc = NULL;
170+
171+  wide = utf8_to_wide_string( utf8_string);
172+
173+  /* 2022-07-25 SMS, et al.  CVE-2022-0530 */
174+  if (wide != NULL)
175+  {
176+    loc = wide_to_local_string( wide, escape_all);
177+    free( wide);
178+  }
179+
180   return loc;
181 }
182 
183-- 
1842.45.2
185