PP/05 FreeBSD compat: handle that Ports no longer create /usr/bin/perl
+JH/16 Drop variables when they go out of scope. Memory management drops a whole
+ region in one operation, for speed, and this leaves assigned pointers
+ dangling. Add checks run only under the testsuite which checks all
+ variables at a store-reset and panics on a dangling pointer; add code
+ explicitly nulling out all the variables discovered. Fixes one known
+ bug: a transport crash, where a dangling pointer for $sending_ip_address
+ originally assigned in a verify callout, is re-used.
+
Exim version 4.88
-----------------
/* Reclaim up the store used in accepting this message */
+ return_path = sender_address = NULL;
+ authenticated_sender = NULL;
+ sending_ip_address = NULL;
+ deliver_host_address = deliver_host =
+ deliver_domain_orig = deliver_localpart_orig = NULL;
+ dnslist_domain = dnslist_matched = NULL;
+#ifndef DISABLE_DKIM
+ dkim_cur_signer = NULL;
+#endif
store_reset(reset_point);
/* If queue_only is set or if there are too many incoming connections in
the incoming host address and an expanded active_hostname. */
log_close_all();
+interface_address =
+sender_host_address = NULL;
store_reset(reset_point);
sender_host_address = NULL;
}
}
else
{
+ int old_pool = store_pool;
+ store_pool = POOL_PERM;
received_protocol = string_copyn(argrest, hn - argrest);
+ store_pool = old_pool;
sender_host_name = hn + 1;
}
}
if (smtp_start_session())
{
- reset_point = store_get(0);
- for (;;)
+ for (reset_point = store_get(0); ; store_reset(reset_point))
{
- store_reset(reset_point);
if (smtp_setup_msg() <= 0) break;
if (!receive_msg(FALSE)) break;
+
+ return_path = sender_address = NULL;
+ dnslist_domain = dnslist_matched = NULL;
+#ifndef DISABLE_DKIM
+ dkim_cur_signer = NULL;
+#endif
+ acl_var_m = NULL;
+ deliver_localpart_orig = NULL;
+ deliver_domain_orig = NULL;
+ callout_address = sending_ip_address = NULL;
+ sender_rate = sender_rate_limit = sender_rate_period = NULL;
}
smtp_log_no_mail();
}
}
else
{
- if (received_protocol == NULL)
+ int old_pool = store_pool;
+ store_pool = POOL_PERM;
+ if (!received_protocol)
received_protocol = string_sprintf("local%s", called_as);
+ store_pool = old_pool;
set_process_info("accepting a local non-SMTP message from <%s>",
sender_address);
}
while (more)
{
- store_reset(reset_point);
message_id[0] = 0;
/* Handle the SMTP case; call smtp_setup_mst() to deal with the initial SMTP
more = receive_msg(extract_recipients);
if (message_id[0] == 0)
{
- if (more) continue;
+ if (more) goto moreloop;
smtp_log_no_mail(); /* Log no mail if configured */
exim_exit(EXIT_FAILURE);
}
#ifndef SIG_IGN_WORKS
while (waitpid(-1, NULL, WNOHANG) > 0);
#endif
+
+moreloop:
+ return_path = sender_address = NULL;
+ authenticated_sender = NULL;
+ deliver_localpart_orig = NULL;
+ deliver_domain_orig = NULL;
+ deliver_host = deliver_host_address = NULL;
+ dnslist_domain = dnslist_matched = NULL;
+ malware_name = NULL;
+ callout_address = NULL;
+ sending_ip_address = NULL;
+ acl_var_m = NULL;
+ { int i; for(i=0; i<REGEX_VARS; i++) regex_vars[i] = NULL; }
+
+ store_reset(reset_point);
}
exim_exit(EXIT_SUCCESS); /* Never returns */
port = ntohs(service_info->s_port);
}
- if ((fd = ip_connectedsocket(SOCK_STREAM, server_name, port, port,
- timeout, NULL, &expand_string_message)) < 0)
+ fd = ip_connectedsocket(SOCK_STREAM, server_name, port, port,
+ timeout, NULL, &expand_string_message);
+ callout_address = NULL;
+ if (fd < 0)
goto SOCK_FAIL;
}
uschar * region_start;
uschar * region_end;
const uschar *var_name;
+ const uschar *var_data;
} err_ctx;
static void
{
err_ctx * e = ctx;
if (var_data >= e->region_start && var_data < e->region_end)
+ {
e->var_name = CUS var_name;
+ e->var_data = CUS var_data;
+ }
}
void
assert_variable_notin(US v->name, *(USS v->value), &e);
if (e.var_name)
- log_write(0, LOG_MAIN|LOG_PANIC_DIE, "live variable '%s' destroyed by reset_store"
- " at %s:%d\n", e.var_name, e.filename, e.linenumber);
+ log_write(0, LOG_MAIN|LOG_PANIC_DIE,
+ "live variable '%s' destroyed by reset_store at %s:%d\n- value '%.64s'",
+ e.var_name, e.filename, e.linenumber, e.var_data);
}
/* Recover store used when reading the header */
+ received_protocol = NULL;
+ sender_address = sender_ident = NULL;
+ authenticated_id = authenticated_sender = NULL;
store_reset(reset_point2);
if (!wanted) continue; /* With next message */
}
/* Now scan the chain and print information, resetting store used
each time. */
-reset_point = store_get(0);
-
-for (; f != NULL; f = f->next)
+for (reset_point = store_get(0); f; f = f->next)
{
int rc, save_errno;
int size = 0;
BOOL env_read;
- store_reset(reset_point);
message_size = 0;
message_subdir[0] = f->dir_uschar;
rc = spool_read_header(f->text, FALSE, count <= 0);
- if (rc == spool_read_notopen && errno == ENOENT && count <= 0) continue;
+ if (rc == spool_read_notopen && errno == ENOENT && count <= 0) goto next;
save_errno = errno;
env_read = (rc == spool_read_OK || rc == spool_read_hdrerror);
/* Collect delivered addresses from any J file */
fname[ptr] = 'J';
- jread = Ufopen(fname, "rb");
- if (jread != NULL)
+ if ((jread = Ufopen(fname, "rb")))
{
while (Ufgets(big_buffer, big_buffer_size, jread) != NULL)
{
fprintf(stdout, "%s ", string_format_size(size, big_buffer));
for (i = 0; i < 16; i++) fputc(f->text[i], stdout);
- if (env_read && sender_address != NULL)
+ if (env_read && sender_address)
{
printf(" <%s>", sender_address);
if (sender_set_untrusted) printf(" (%s)", originator_login);
if (rc != spool_read_hdrerror)
{
printf("\n\n");
- continue;
+ goto next;
}
}
printf("\n");
- if (recipients_list != NULL)
+ if (recipients_list)
{
for (i = 0; i < recipients_count; i++)
{
if (!delivered || option != 1)
printf(" %s %s\n", (delivered != NULL)? "D":" ",
recipients_list[i].address);
- if (delivered != NULL) delivered->data.val = TRUE;
+ if (delivered) delivered->data.val = TRUE;
}
- if (option == 2 && tree_nonrecipients != NULL)
+ if (option == 2 && tree_nonrecipients)
queue_list_extras(tree_nonrecipients);
printf("\n");
}
+
+next:
+ received_protocol = NULL;
+ sender_fullhost = sender_helo_name =
+ sender_rcvhost = sender_host_address = sender_address = sender_ident = NULL;
+ sender_host_authenticated = authenticated_sender = authenticated_id = NULL;
+ interface_address = NULL;
+ acl_var_m = NULL;
+
+ store_reset(reset_point);
}
}
static void
smtp_reset(void *reset_point)
{
-store_reset(reset_point);
recipients_list = NULL;
rcpt_count = rcpt_defer_count = rcpt_fail_count =
raw_recipients_count = recipients_count = recipients_list_max = 0;
suppress_local_fixups = suppress_local_fixups_default; /* Can be set by ACL */
active_local_from_check = local_from_check; /* Can be set by ACL */
active_local_sender_retain = local_sender_retain; /* Can be set by ACL */
-sender_address = NULL;
+sending_ip_address = NULL;
+return_path = sender_address = NULL;
+sender_data = NULL; /* Can be set by ACL */
+deliver_localpart_orig = NULL;
+deliver_domain_orig = NULL;
+callout_address = NULL;
submission_name = NULL; /* Can be set by ACL */
raw_sender = NULL; /* After SMTP rewrite, before qualifying */
sender_address_unrewritten = NULL; /* Set only after verify rewrite */
bmi_run = 0;
bmi_verdicts = NULL;
#endif
+dnslist_domain = dnslist_matched = NULL;
#ifndef DISABLE_DKIM
dkim_signers = NULL;
dkim_disable_verify = FALSE;
#endif
dsn_ret = 0;
dsn_envid = NULL;
+deliver_host = deliver_host_address = NULL; /* Can be set by ACL */
#ifndef DISABLE_PRDR
prdr_requested = FALSE;
#endif
not the first message in an SMTP session and the previous message caused them
to be referenced in an ACL. */
-if (message_body != NULL)
+if (message_body)
{
store_free(message_body);
message_body = NULL;
}
-if (message_body_end != NULL)
+if (message_body_end)
{
store_free(message_body_end);
message_body_end = NULL;
repetition in the same message, but it seems right to repeat them for different
messages. */
-while (acl_warn_logged != NULL)
+while (acl_warn_logged)
{
string_item *this = acl_warn_logged;
acl_warn_logged = acl_warn_logged->next;
store_free(this);
}
+store_reset(reset_point);
}
case ENV_MAIL_OPT_UTF8:
if (smtputf8_advertised)
{
+ int old_pool = store_pool;
+
DEBUG(D_receive) debug_printf("smtputf8 requested\n");
message_smtputf8 = allow_utf8_domains = TRUE;
+ store_pool = POOL_PERM;
received_protocol = string_sprintf("utf8%s", received_protocol);
+ store_pool = old_pool;
}
break;
#endif