Chunking: do not treat the first lonely dot special. CVE-2017-16944, Bug 2201
[exim.git] / src / src / receive.c
index e7e518a921b3c3e6d42ac16ff978ac9f18b52940..ae2c93b4efd56419c588b4c868d5047c4d57f244 100644 (file)
@@ -1810,8 +1810,8 @@ for (;;)
   (and sometimes lunatic messages can have ones that are 100s of K long) we
   call store_release() for strings that have been copied - if the string is at
   the start of a block (and therefore the only thing in it, because we aren't
-  doing any other gets), the block gets freed. We can only do this because we
-  know there are no other calls to store_get() going on. */
+  doing any other gets), the block gets freed. We can only do this release if
+  there were no allocations since the once that we want to free. */
 
   if (ptr >= header_size - 4)
     {
@@ -1819,12 +1819,7 @@ for (;;)
     /* header_size += 256; */
     header_size *= 2;
     if (!store_extend(next->text, oldsize, header_size))
-      {
-      uschar *newtext = store_get(header_size);
-      memcpy(newtext, next->text, ptr);
-      store_release(next->text);
-      next->text = newtext;
-      }
+      next->text = store_newblock(next->text, header_size, ptr);
     }
 
   /* Cope with receiving a binary zero. There is dispute about whether
@@ -1864,7 +1859,7 @@ for (;;)
   prevent further reading), and break out of the loop, having freed the
   empty header, and set next = NULL to indicate no data line. */
 
-  if (ptr == 0 && ch == '.' && (smtp_input || dot_ends))
+  if (ptr == 0 && ch == '.' && dot_ends)
     {
     ch = (receive_getc)(GETC_BUFFER_UNLIMITED);
     if (ch == '\r')
@@ -3442,7 +3437,7 @@ else
              continue;
              }
 
-           seen_items = string_catn(seen_items, ":", 1);
+           seen_items = string_catn(seen_items, US":", 1);
            }
          seen_items = string_cat(seen_items, item);
 
@@ -3774,32 +3769,32 @@ else
   switch(rc)
     {
     default:
-    log_write(0, LOG_MAIN, "invalid return %d from local_scan(). Temporary "
-      "rejection given", rc);
-    goto TEMPREJECT;
+      log_write(0, LOG_MAIN, "invalid return %d from local_scan(). Temporary "
+       "rejection given", rc);
+      goto TEMPREJECT;
 
     case LOCAL_SCAN_REJECT_NOLOGHDR:
-    BIT_CLEAR(log_selector, log_selector_size, Li_rejected_header);
-    /* Fall through */
+      BIT_CLEAR(log_selector, log_selector_size, Li_rejected_header);
+      /* Fall through */
 
     case LOCAL_SCAN_REJECT:
-    smtp_code = US"550";
-    if (errmsg == NULL) errmsg =  US"Administrative prohibition";
-    break;
+      smtp_code = US"550";
+      if (!errmsg) errmsg =  US"Administrative prohibition";
+      break;
 
     case LOCAL_SCAN_TEMPREJECT_NOLOGHDR:
-    BIT_CLEAR(log_selector, log_selector_size, Li_rejected_header);
-    /* Fall through */
+      BIT_CLEAR(log_selector, log_selector_size, Li_rejected_header);
+      /* Fall through */
 
     case LOCAL_SCAN_TEMPREJECT:
     TEMPREJECT:
-    smtp_code = US"451";
-    if (errmsg == NULL) errmsg = US"Temporary local problem";
-    istemp = US"temporarily ";
-    break;
+      smtp_code = US"451";
+      if (!errmsg) errmsg = US"Temporary local problem";
+      istemp = US"temporarily ";
+      break;
     }
 
-  g = string_append(g, 2, US"F=",
+  g = string_append(NULL, 2, US"F=",
     sender_address[0] == 0 ? US"<>" : sender_address);
   g = add_host_info_for_log(g);