]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-smtp: server: recipient: Hold a reference to the recipient while calling a non...
authorStephan Bosch <stephan.bosch@dovecot.fi>
Thu, 1 Nov 2018 00:14:50 +0000 (01:14 +0100)
committerStephan Bosch <stephan.bosch@dovecot.fi>
Thu, 1 Nov 2018 21:23:45 +0000 (22:23 +0100)
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).

src/lib-smtp/smtp-server-cmd-rcpt.c
src/lib-smtp/smtp-server-private.h
src/lib-smtp/smtp-server-recipient.c

index 4eff2974eb35b1f2c3424fcdc50ff71b1b03d289..f9a9a8586f4f0837425ec82b817be1fb7a428279 100644 (file)
@@ -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
index da4a090f9b5bdf326c8be169268db894889d6c29..380534787569cb83ab3051083347b9263e64ae4f 100644 (file)
@@ -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);
 
index 24a752c85cc3d58fe5518388c91c33da84af4052..53b393868c7f4e4955cb0c59debdb4aff037b347 100644 (file)
@@ -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;
 }