CVE-2020-28019: Failure to reset function pointer after BDAT error
authorJeremy Harris <jgh146exb@wizmail.org>
Thu, 4 Mar 2021 21:19:08 +0000 (22:19 +0100)
committerHeiko Schlittermann (HS12-RIPE) <hs@schlittermann.de>
Thu, 27 May 2021 19:30:41 +0000 (21:30 +0200)
Based on Phil Pennock's commits 4715403e and 151ffd72, and Jeremy
Harris's commits aa171254 and 9aceb5c2.

(cherry picked from commit 0a3fbb7e3be375bc93b8e359c6aff333c7c2d76f)
(cherry picked from commit 99d057fad97a2def9f000ebccda83e4008112819)

src/src/smtp_in.c

index b6d530f93482b692a5712884e0328353b0904ed2..6d23397702dc2d8ac2a609ab2bd0eff04694dc3a 100644 (file)
@@ -794,15 +794,22 @@ else
   }
 
 receive_getc = bdat_getc;
   }
 
 receive_getc = bdat_getc;
+receive_getbuf = bdat_getbuf;
 receive_ungetc = bdat_ungetc;
 }
 
 static inline void
 bdat_pop_receive_functions(void)
 {
 receive_ungetc = bdat_ungetc;
 }
 
 static inline void
 bdat_pop_receive_functions(void)
 {
+if (lwr_receive_getc == NULL)
+  {
+  DEBUG(D_receive) debug_printf("chunking double-pop receive functions\n");
+  return;
+  }
 receive_getc = lwr_receive_getc;
 receive_getbuf = lwr_receive_getbuf;
 receive_ungetc = lwr_receive_ungetc;
 receive_getc = lwr_receive_getc;
 receive_getbuf = lwr_receive_getbuf;
 receive_ungetc = lwr_receive_ungetc;
+
 lwr_receive_getc = NULL;
 lwr_receive_getbuf = NULL;
 lwr_receive_ungetc = NULL;
 lwr_receive_getc = NULL;
 lwr_receive_getbuf = NULL;
 lwr_receive_ungetc = NULL;
@@ -5341,7 +5348,7 @@ while (done <= 0)
       DEBUG(D_receive) debug_printf("chunking state %d, %d bytes\n",
                                    (int)chunking_state, chunking_data_left);
 
       DEBUG(D_receive) debug_printf("chunking state %d, %d bytes\n",
                                    (int)chunking_state, chunking_data_left);
 
-      f.bdat_readers_wanted = TRUE;
+      f.bdat_readers_wanted = TRUE; /* FIXME: redundant vs chunking_state? */
       f.dot_ends = FALSE;
 
       goto DATA_BDAT;
       f.dot_ends = FALSE;
 
       goto DATA_BDAT;
@@ -5391,6 +5398,12 @@ while (done <= 0)
        sender_address = NULL;  /* This will allow a new MAIL without RSET */
        sender_address_unrewritten = NULL;
        smtp_printf("554 Too many recipients\r\n", FALSE);
        sender_address = NULL;  /* This will allow a new MAIL without RSET */
        sender_address_unrewritten = NULL;
        smtp_printf("554 Too many recipients\r\n", FALSE);
+
+       if (chunking_state > CHUNKING_OFFERED)
+         {
+         bdat_push_receive_functions();
+         bdat_flush_data();
+         }
        break;
        }
 
        break;
        }