From: Stephan Bosch Date: Thu, 1 Nov 2018 00:14:50 +0000 (+0100) Subject: lib-smtp: server: recipient: Hold a reference to the recipient while calling a non... X-Git-Tag: 2.3.9~1103 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=7197689fd947bb731b8027ce8cd9d5c981870ee3;p=thirdparty%2Fdovecot%2Fcore.git lib-smtp: server: recipient: Hold a reference to the recipient while calling a non-destroy hook. Prevents memory problems when the hook inadvertently gets the recipient destroyed. Unlike the server command, this is not strictly necessary for the recipient object, but we add this anyway to prevent future problems when the recipient implementation becomes more complex (e.g. with additional hooks). --- diff --git a/src/lib-smtp/smtp-server-cmd-rcpt.c b/src/lib-smtp/smtp-server-cmd-rcpt.c index 4eff2974eb..f9a9a8586f 100644 --- a/src/lib-smtp/smtp-server-cmd-rcpt.c +++ b/src/lib-smtp/smtp-server-cmd-rcpt.c @@ -66,7 +66,7 @@ cmd_rcpt_completed(struct smtp_server_cmd_ctx *cmd, /* success */ data->rcpt = NULL; /* clear to prevent destruction */ - smtp_server_recipient_approved(rcpt); + (void)smtp_server_recipient_approved(&rcpt); } static void diff --git a/src/lib-smtp/smtp-server-private.h b/src/lib-smtp/smtp-server-private.h index da4a090f9b..3805347875 100644 --- a/src/lib-smtp/smtp-server-private.h +++ b/src/lib-smtp/smtp-server-private.h @@ -381,7 +381,7 @@ void smtp_server_recipient_ref(struct smtp_server_recipient *rcpt); bool smtp_server_recipient_unref(struct smtp_server_recipient **_rcpt); void smtp_server_recipient_destroy(struct smtp_server_recipient **_rcpt); -void smtp_server_recipient_approved(struct smtp_server_recipient *rcpt); +bool smtp_server_recipient_approved(struct smtp_server_recipient **_rcpt); void smtp_server_recipient_last_data(struct smtp_server_recipient *rcpt, struct smtp_server_cmd_ctx *cmd); diff --git a/src/lib-smtp/smtp-server-recipient.c b/src/lib-smtp/smtp-server-recipient.c index 24a752c85c..53b393868c 100644 --- a/src/lib-smtp/smtp-server-recipient.c +++ b/src/lib-smtp/smtp-server-recipient.c @@ -6,8 +6,8 @@ #include "smtp-server-private.h" -static void -smtp_server_recipient_call_hooks(struct smtp_server_recipient *rcpt, +static bool +smtp_server_recipient_call_hooks(struct smtp_server_recipient **_rcpt, enum smtp_server_recipient_hook_type type); struct smtp_server_recipient * @@ -57,8 +57,9 @@ bool smtp_server_recipient_unref(struct smtp_server_recipient **_rcpt) return TRUE; prcpt->destroying = TRUE; - smtp_server_recipient_call_hooks( - rcpt, SMTP_SERVER_RECIPIENT_HOOK_DESTROY); + if (!smtp_server_recipient_call_hooks( + &rcpt, SMTP_SERVER_RECIPIENT_HOOK_DESTROY)) + i_unreached(); pool_unref(&rcpt->pool); return FALSE; @@ -69,8 +70,9 @@ void smtp_server_recipient_destroy(struct smtp_server_recipient **_rcpt) smtp_server_recipient_unref(_rcpt); } -void smtp_server_recipient_approved(struct smtp_server_recipient *rcpt) +bool smtp_server_recipient_approved(struct smtp_server_recipient **_rcpt) { + struct smtp_server_recipient *rcpt = *_rcpt; struct smtp_server_transaction *trans = rcpt->conn->state.trans; i_assert(trans != NULL); @@ -78,8 +80,8 @@ void smtp_server_recipient_approved(struct smtp_server_recipient *rcpt) rcpt->cmd = NULL; smtp_server_transaction_add_rcpt(trans, rcpt); - smtp_server_recipient_call_hooks( - rcpt, SMTP_SERVER_RECIPIENT_HOOK_APPROVED); + return smtp_server_recipient_call_hooks( + _rcpt, SMTP_SERVER_RECIPIENT_HOOK_APPROVED); } void smtp_server_recipient_last_data(struct smtp_server_recipient *rcpt, @@ -143,14 +145,18 @@ void smtp_server_recipient_remove_hook( i_assert(found); } -static void -smtp_server_recipient_call_hooks(struct smtp_server_recipient *rcpt, +static bool +smtp_server_recipient_call_hooks(struct smtp_server_recipient **_rcpt, enum smtp_server_recipient_hook_type type) { + struct smtp_server_recipient *rcpt = *_rcpt; struct smtp_server_recipient_private *prcpt = (struct smtp_server_recipient_private *)rcpt; struct smtp_server_recipient_hook *hook; + if (type != SMTP_SERVER_RECIPIENT_HOOK_DESTROY) + smtp_server_recipient_ref(rcpt); + hook = prcpt->hooks_head; while (hook != NULL) { struct smtp_server_recipient_hook *hook_next = hook->next; @@ -163,4 +169,12 @@ smtp_server_recipient_call_hooks(struct smtp_server_recipient *rcpt, hook = hook_next; } + + if (type != SMTP_SERVER_RECIPIENT_HOOK_DESTROY) { + if (!smtp_server_recipient_unref(&rcpt)) { + *_rcpt = NULL; + return FALSE; + } + } + return TRUE; }