CVE-2020-28022: Heap out-of-bounds read and write in extract_option()
authorHeiko Schlittermann (HS12-RIPE) <hs@schlittermann.de>
Mon, 29 Mar 2021 21:12:02 +0000 (23:12 +0200)
committerHeiko Schlittermann (HS12-RIPE) <hs@schlittermann.de>
Thu, 27 May 2021 19:30:50 +0000 (21:30 +0200)
Based on Phil Pennock's commit c5017adf.

(cherry picked from commit 9e941e1807b624b255c9ec0f41a0b3a89e144de3)
(cherry picked from commit 33d4c87653ddbbea9fd8cb8eb2ff78c149850006)

src/src/smtp_in.c

index 6d23397702dc2d8ac2a609ab2bd0eff04694dc3a..9efe7baa9a9b357aa0937354c9d0b3df0a8f5145 100644 (file)
@@ -2003,30 +2003,35 @@ static BOOL
 extract_option(uschar **name, uschar **value)
 {
 uschar *n;
 extract_option(uschar **name, uschar **value)
 {
 uschar *n;
-uschar *v = smtp_cmd_data + Ustrlen(smtp_cmd_data) - 1;
-while (isspace(*v)) v--;
-v[1] = '\0';
+uschar *v;
+if (Ustrlen(smtp_cmd_data) <= 0) return FALSE;
+v = smtp_cmd_data + Ustrlen(smtp_cmd_data) - 1;
+while (v > smtp_cmd_data && isspace(*v)) v--;
+v[1] = 0;
+
 while (v > smtp_cmd_data && *v != '=' && !isspace(*v))
   {
   /* Take care to not stop at a space embedded in a quoted local-part */
 while (v > smtp_cmd_data && *v != '=' && !isspace(*v))
   {
   /* Take care to not stop at a space embedded in a quoted local-part */
-
-  if ((*v == '"') && (v > smtp_cmd_data + 1))
-    do v--; while (*v != '"' && v > smtp_cmd_data+1);
+  if (*v == '"')
+    {
+    do v--; while (v > smtp_cmd_data && *v != '"');
+    if (v <= smtp_cmd_data) return FALSE;
+    }
   v--;
   }
   v--;
   }
+if (v <= smtp_cmd_data) return FALSE;
 
 n = v;
 if (*v == '=')
   {
 
 n = v;
 if (*v == '=')
   {
-  while(isalpha(n[-1])) n--;
+  while (n > smtp_cmd_data && isalpha(n[-1])) n--;
   /* RFC says SP, but TAB seen in wild and other major MTAs accept it */
   /* RFC says SP, but TAB seen in wild and other major MTAs accept it */
-  if (!isspace(n[-1])) return FALSE;
+  if (n <= smtp_cmd_data || !isspace(n[-1])) return FALSE;
   n[-1] = 0;
   }
 else
   {
   n++;
   n[-1] = 0;
   }
 else
   {
   n++;
-  if (v == smtp_cmd_data) return FALSE;
   }
 *v++ = 0;
 *name = n;
   }
 *v++ = 0;
 *name = n;