Fix validation of domain-literals in Message_ID: headers. Bug 2805
[exim.git] / src / src / receive.c
index 3a3f73e87319013fffae74477101530359f81fcc..5471aa7cb94aa009ccc3c77a0f4cc5cfccc8e17a 100644 (file)
@@ -486,18 +486,18 @@ Returns:      nothing
 void
 receive_add_recipient(uschar *recipient, int pno)
 {
-/* XXX This is a math limit; we should consider a performance/sanity limit too. */
-const int safe_recipients_limit = INT_MAX / sizeof(recipient_item) - 1;
-
 if (recipients_count >= recipients_list_max)
   {
   recipient_item *oldlist = recipients_list;
   int oldmax = recipients_list_max;
-  recipients_list_max = recipients_list_max ? 2*recipients_list_max : 50;
-  if ((recipients_list_max >= safe_recipients_limit) || (recipients_list_max < 0))
+
+  const int safe_recipients_limit = INT_MAX / 2 / sizeof(recipient_item);
+  if (recipients_list_max < 0 || recipients_list_max >= safe_recipients_limit)
     {
-    log_write(0, LOG_MAIN|LOG_PANIC, "Too many recipients needed: %d not satisfiable", recipients_list_max);
+    log_write(0, LOG_MAIN|LOG_PANIC_DIE, "Too many recipients: %d", recipients_list_max);
     }
+
+  recipients_list_max = recipients_list_max ? 2*recipients_list_max : 50;
   recipients_list = store_get(recipients_list_max * sizeof(recipient_item), FALSE);
   if (oldlist)
     memcpy(recipients_list, oldlist, oldmax * sizeof(recipient_item));
@@ -1663,7 +1663,6 @@ int  process_info_len = Ustrlen(process_info);
 int  error_rc = error_handling == ERRORS_SENDER
        ? errors_sender_rc : EXIT_FAILURE;
 int  header_size = 256;
-int  start, end, domain;
 int  id_resolution = 0;
 int  had_zero = 0;
 int  prevlines_length = 0;
@@ -1788,15 +1787,19 @@ if (sender_host_address) dmarc_init();  /* initialize libopendmarc */
 
 /* Remember the time of reception. Exim uses time+pid for uniqueness of message
 ids, and fractions of a second are required. See the comments that precede the
-message id creation below. */
+message id creation below.
+We use a routine that if possible uses a monotonic clock, and can be used again
+after reception for the tick-wait even under the Linux non-Posix behaviour. */
 
 exim_gettime(&message_id_tv);
 
 /* For other uses of the received time we can operate with granularity of one
 second, and for that we use the global variable received_time. This is for
-things like ultimate message timeouts. */
+things like ultimate message timeouts.
+For this we do not care about the Linux suspend/resume problem, so rather than
+use exim_gettime() everywhere we use a plain gettimeofday() here. */
 
-received_time = message_id_tv;
+gettimeofday(&received_time, NULL);
 
 /* If SMTP input, set the special handler for timeouts. The alarm() calls
 happen in the smtp_getc() function when it refills its buffer. */
@@ -2561,11 +2564,12 @@ if (extract_recip)
           &domain, FALSE);
 
 #ifdef SUPPORT_I18N
-       if (string_is_utf8(recipient))
-         message_smtputf8 = TRUE;
-       else
-         allow_utf8_domains = b;
+        if (recipient)
+          if (string_is_utf8(recipient)) message_smtputf8 = TRUE;
+          else allow_utf8_domains = b;
        }
+#else
+        ;
 #endif
 
         /* Keep a list of all the bad addresses so we can send a single
@@ -4079,6 +4083,8 @@ if (  LOGGING(msg_id) && msgid_header
   uschar * old_id;
   BOOL save_allow_domain_literals = allow_domain_literals;
   allow_domain_literals = TRUE;
+  int start, end, domain;
+
   old_id = parse_extract_address(Ustrchr(msgid_header->text, ':') + 1,
     &errmsg, &start, &end, &domain, FALSE);
   allow_domain_literals = save_allow_domain_literals;
@@ -4325,7 +4331,10 @@ pid can be re-used within our time interval. We can't shorten the interval
 without re-designing the message-id. See comments above where the message id is
 created. This is Something For The Future.
 Do this wait any time we have created a message-id, even if we rejected the
-message.  This gives unique IDs for logging done by ACLs. */
+message.  This gives unique IDs for logging done by ACLs.
+The initial timestamp must have been obtained via exim_gettime() to avoid
+issues on Linux with suspend/resume.
+It would be Nicer to only pause before a follow-on message. */
 
 if (id_resolution != 0)
   {