]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
app_voicemail: Fix stack overrun in append_mailbox
authorGeorge Joseph <gjoseph@digium.com>
Fri, 21 Sep 2018 19:32:52 +0000 (13:32 -0600)
committerGeorge Joseph <gjoseph@digium.com>
Fri, 21 Sep 2018 21:07:09 +0000 (16:07 -0500)
The append_mailbox function wasn't calculating the correct length
to pass to ast_alloca and it wasn't handling the case where context
might be empty.

Found by the Address Sanitizer.

Change-Id: I7eb51c7bd18a7a8dbdba261462a95cc69e84f161

apps/app_voicemail.c

index 74c32f529fb0d129b58cbe7eb5d4ece17a61dacd..fafc82123dd0ba44f4ce116ecc7fc1401708b62e 100644 (file)
@@ -793,11 +793,16 @@ struct baseio {
        unsigned char iobuf[BASEMAXINLINE];
 };
 
+#define MAX_VM_MBOX_ID_LEN (AST_MAX_EXTENSION)
+#define MAX_VM_CONTEXT_LEN (AST_MAX_CONTEXT)
+/* MAX_VM_MAILBOX_LEN allows enough room for the '@' and NULL terminator */
+#define MAX_VM_MAILBOX_LEN (MAX_VM_MBOX_ID_LEN + MAX_VM_CONTEXT_LEN)
+
 /*! Structure for linked list of users
  * Use ast_vm_user_destroy() to free one of these structures. */
 struct ast_vm_user {
-       char context[AST_MAX_CONTEXT];   /*!< Voicemail context */
-       char mailbox[AST_MAX_EXTENSION]; /*!< Mailbox id, unique within vm context */
+       char context[MAX_VM_CONTEXT_LEN];/*!< Voicemail context */
+       char mailbox[MAX_VM_MBOX_ID_LEN];/*!< Mailbox id, unique within vm context */
        char password[80];               /*!< Secret pin code, numbers only */
        char fullname[80];               /*!< Full name, for directory app */
        char *email;                     /*!< E-mail address */
@@ -12269,23 +12274,21 @@ static int mark_or_create_poll_state(struct ast_vm_user *vmu)
 {
        size_t len;
        struct poll_state *poll_state;
-       char *mailbox;
+       char mailbox_full[MAX_VM_MAILBOX_LEN];
 
        if (ast_strlen_zero(vmu->mailbox)) {
                ast_log(LOG_ERROR, "Mailbox can't be empty\n");
                return -1;
        }
 
-       len = sizeof(vmu->mailbox) + sizeof(vmu->context) + sizeof('@') + 1;
-       mailbox = ast_alloca(len);
-       len = snprintf(mailbox, len, "%s%s%s",
+       len = snprintf(mailbox_full, MAX_VM_MAILBOX_LEN, "%s%s%s",
                vmu->mailbox,
                ast_strlen_zero(vmu->context) ? "" : "@",
                vmu->context);
 
        len++; /* For NULL terminator */
 
-       poll_state = ao2_find(poll_list, mailbox, OBJ_SEARCH_KEY);
+       poll_state = ao2_find(poll_list, mailbox_full, OBJ_SEARCH_KEY);
        if (poll_state) {
                poll_state->marked_used = 1;
                ao2_ref(poll_state, -1);
@@ -12297,7 +12300,7 @@ static int mark_or_create_poll_state(struct ast_vm_user *vmu)
        if (!poll_state) {
                return -1;
        }
-       strcpy(poll_state->mailbox, mailbox); /* Safe */
+       strcpy(poll_state->mailbox, mailbox_full); /* Safe */
        poll_state->marked_used = 1;
 
        ao2_link_flags(poll_list, poll_state, OBJ_NOLOCK);
@@ -12362,7 +12365,7 @@ static int append_mailbox(const char *context, const char *box, const char *data
        char *stringp;
        char *s;
        struct ast_vm_user *vmu;
-       char *mailbox_full;
+       char mailbox_full[MAX_VM_MAILBOX_LEN];
        int new = 0, old = 0, urgent = 0;
        char secretfn[PATH_MAX] = "";
 
@@ -12401,10 +12404,10 @@ static int append_mailbox(const char *context, const char *box, const char *data
                read_password_from_file(secretfn, vmu->password, sizeof(vmu->password));
        }
 
-       mailbox_full = ast_alloca(strlen(box) + strlen(context) + 1);
-       strcpy(mailbox_full, box);
-       strcat(mailbox_full, "@");
-       strcat(mailbox_full, context);
+       snprintf(mailbox_full, MAX_VM_MAILBOX_LEN, "%s%s%s",
+               box,
+               ast_strlen_zero(context) ? "" : "@",
+               context);
 
        inboxcount2(mailbox_full, &urgent, &new, &old);
 #ifdef IMAP_STORAGE