The ACCOUNT structure is unusual inside the Mutt codebase.  It's never
dynamically allocated: instead it's a member of the CONNECTION and
IMAP_MBOX structures.  This commit doesn't change that.

This commit does change the individual string fields from fixed size
char arrays to dynamically allocated strings.  This is done because
other variables, such as $imap_user and $imap_pass, have no fixed size
limit.  In the past, I've had to bump up the size of the fields to
accomodate users with extra large username or passwords.

Unfortunately, this change leads to lifecyle issues.  We need to track
and free the fields.

This commit therefore creates helper functions:
- mutt_account_free() to free the fields
- mutt_account_copy() to strdup the fields
- imap_mbox_free() to free the IMAP_MBOX and its ACCOUNT fields.

A call to mutt_account_free() is added to mutt_socket_free(): the only
place that cleans up CONNECTION structures.

Other places in the code swap out a call to FREE(imapbox.mbox) to
imap_mbox_free(&imapmbox);

IMAP_MBOX variables are all initialized to { 0 } to ensure the dynamic
string fields are initilized to NULL, and thus ensure the free
function works correctly.

Another potential complication is the ciss_url_t structure.  It points
directly at ACCOUNT fields, instead of allocating them.  This is
dangerous, of course, but this commit doesn't change the lifecycle of
the ACCOUNT or ciss_url_t.
---
 account.c      | 72 ++++++++++++++++++++++++++++++++++++++------------
 account.h      | 10 ++++---
 browser.c      |  5 ++--
 imap/browse.c  | 26 +++++++++---------
 imap/command.c |  7 ++---
 imap/imap.c    | 52 ++++++++++++++++++------------------
 imap/imap.h    |  1 +
 imap/message.c | 10 +++----
 imap/util.c    | 42 ++++++++++++++++++-----------
 mutt_socket.c  |  4 ++-
 pop_auth.c     |  2 +-
 11 files changed, 144 insertions(+), 87 deletions(-)

diff --git a/account.c b/account.c
index 70fe2705..dcb59b36 100644
--- a/account.c
+++ b/account.c
@@ -27,6 +27,40 @@
 #include "url.h"
 #include "mutt_curses.h"
 
+/* Accounts aren't independently allocated.  They are members of the
+ * CONNECTION and IMAP_DATA structs.  This function frees the char*
+ * members of the ACCOUNT and resets the integer values in case the
+ * structure is reused in a loop.
+ */
+void mutt_account_free(ACCOUNT *account)
+{
+  if (!account)
+    return;
+
+  FREE(&account->user);
+  FREE(&account->login);
+  FREE(&account->pass);
+  FREE(&account->host);
+  account->port = 0;
+  account->type = 0;
+  account->flags = 0;
+}
+
+void mutt_account_copy(ACCOUNT *dest, const ACCOUNT *src)
+{
+  if (!dest || !src)
+    return;
+
+  dest->user = safe_strdup(src->user);
+  dest->login = safe_strdup(src->login);
+  dest->pass = safe_strdup(src->pass);
+  dest->host = safe_strdup(src->host);
+  dest->port = src->port;
+  dest->type = src->type;
+  dest->flags = src->flags;
+}
+
+
 /* mutt_account_match: compare account info (host/port/user) */
 int mutt_account_match(const ACCOUNT *a1, const ACCOUNT *a2)
 {
@@ -53,11 +87,11 @@ int mutt_account_match(const ACCOUNT *a1, const ACCOUNT *a2)
 #endif
 
   if (a1->flags & a2->flags & MUTT_ACCT_USER)
-    return (!strcmp(a1->user, a2->user));
+    return (!mutt_strcmp(a1->user, a2->user));
   if (a1->flags & MUTT_ACCT_USER)
-    return (!strcmp(a1->user, user));
+    return (!mutt_strcmp(a1->user, user));
   if (a2->flags & MUTT_ACCT_USER)
-    return (!strcmp(a2->user, user));
+    return (!mutt_strcmp(a2->user, user));
 
   return 1;
 }
@@ -67,19 +101,19 @@ int mutt_account_fromurl(ACCOUNT *account, ciss_url_t *url)
 {
   /* must be present */
   if (url->host)
-    strfcpy(account->host, url->host, sizeof(account->host));
+    mutt_str_replace(&account->host, url->host);
   else
     return -1;
 
   if (url->user)
   {
-    strfcpy(account->user, url->user, sizeof(account->user));
+    mutt_str_replace(&account->user, url->user);
     account->flags |= MUTT_ACCT_USER;
     account->flags |= MUTT_ACCT_USER_FROM_URL;
   }
   if (url->pass)
   {
-    strfcpy(account->pass, url->pass, sizeof(account->pass));
+    mutt_str_replace(&account->pass, url->pass);
     account->flags |= MUTT_ACCT_PASS;
     account->flags |= MUTT_ACCT_PASS_FROM_URL;
   }
@@ -161,17 +195,18 @@ void mutt_account_tourl(ACCOUNT *account, ciss_url_t 
*url, int force_user)
 int mutt_account_getuser(ACCOUNT *account)
 {
   char prompt[SHORT_STRING];
+  char userbuf[LONG_STRING];
 
   /* already set */
   if (account->flags & MUTT_ACCT_USER)
     return 0;
 #ifdef USE_IMAP
   else if ((account->type == MUTT_ACCT_TYPE_IMAP) && ImapUser)
-    strfcpy(account->user, ImapUser, sizeof(account->user));
+    mutt_str_replace(&account->user, ImapUser);
 #endif
 #ifdef USE_POP
   else if ((account->type == MUTT_ACCT_TYPE_POP) && PopUser)
-    strfcpy(account->user, PopUser, sizeof(account->user));
+    mutt_str_replace(&account->user, PopUser);
 #endif
   else if (option(OPTNOCURSES))
     return -1;
@@ -179,9 +214,10 @@ int mutt_account_getuser(ACCOUNT *account)
   else
   {
     snprintf(prompt, sizeof(prompt), _("Username at %s: "), account->host);
-    strfcpy(account->user, NONULL(Username), sizeof(account->user));
-    if (mutt_get_field_unbuffered(prompt, account->user, 
sizeof(account->user), 0))
+    strfcpy(userbuf, NONULL(Username), sizeof(userbuf));
+    if (mutt_get_field_unbuffered(prompt, userbuf, sizeof(userbuf), 0))
       return -1;
+    mutt_str_replace(&account->user, userbuf);
   }
 
   account->flags |= MUTT_ACCT_USER;
@@ -199,7 +235,7 @@ int mutt_account_getlogin(ACCOUNT *account)
   {
     if (ImapLogin)
     {
-      strfcpy(account->login, ImapLogin, sizeof(account->login));
+      mutt_str_replace(&account->login, ImapLogin);
       account->flags |= MUTT_ACCT_LOGIN;
     }
   }
@@ -208,7 +244,7 @@ int mutt_account_getlogin(ACCOUNT *account)
   if (!(account->flags & MUTT_ACCT_LOGIN))
   {
     mutt_account_getuser(account);
-    strfcpy(account->login, account->user, sizeof(account->login));
+    mutt_str_replace(&account->login, account->user);
   }
 
   account->flags |= MUTT_ACCT_LOGIN;
@@ -231,29 +267,31 @@ int _mutt_account_getpass(ACCOUNT *account,
                           void (*prompt_func)(char *, size_t, ACCOUNT *))
 {
   char prompt[SHORT_STRING];
+  char passbuf[LONG_STRING];
 
   if (account->flags & MUTT_ACCT_PASS)
     return 0;
 #ifdef USE_IMAP
   else if ((account->type == MUTT_ACCT_TYPE_IMAP) && ImapPass)
-    strfcpy(account->pass, ImapPass, sizeof(account->pass));
+    mutt_str_replace(&account->pass, ImapPass);
 #endif
 #ifdef USE_POP
   else if ((account->type == MUTT_ACCT_TYPE_POP) && PopPass)
-    strfcpy(account->pass, PopPass, sizeof(account->pass));
+    mutt_str_replace(&account->pass, PopPass);
 #endif
 #ifdef USE_SMTP
   else if ((account->type == MUTT_ACCT_TYPE_SMTP) && SmtpPass)
-    strfcpy(account->pass, SmtpPass, sizeof(account->pass));
+    mutt_str_replace(&account->pass, SmtpPass);
 #endif
   else if (option(OPTNOCURSES))
     return -1;
   else
   {
     prompt_func(prompt, sizeof(prompt), account);
-    account->pass[0] = '\0';
-    if (mutt_get_password(prompt, account->pass, sizeof(account->pass)))
+    passbuf[0] = '\0';
+    if (mutt_get_password(prompt, passbuf, sizeof(passbuf)))
       return -1;
+    mutt_str_replace(&account->pass, passbuf);
   }
 
   account->flags |= MUTT_ACCT_PASS;
diff --git a/account.h b/account.h
index 3361fdc4..137a7bb6 100644
--- a/account.h
+++ b/account.h
@@ -44,15 +44,17 @@ enum
 
 typedef struct
 {
-  char user[128];
-  char login[128];
-  char pass[256];
-  char host[128];
+  char *user;
+  char *login;
+  char *pass;
+  char *host;
   unsigned short port;
   unsigned char type;
   unsigned char flags;
 } ACCOUNT;
 
+void mutt_account_free(ACCOUNT *account);
+void mutt_account_copy(ACCOUNT *dest, const ACCOUNT *src);
 int mutt_account_match(const ACCOUNT *a1, const ACCOUNT *m2);
 int mutt_account_fromurl(ACCOUNT *account, ciss_url_t *url);
 void mutt_account_tourl(ACCOUNT *account, ciss_url_t *url, int force_user);
diff --git a/browser.c b/browser.c
index 77d64174..687df3a3 100644
--- a/browser.c
+++ b/browser.c
@@ -1221,12 +1221,13 @@ void _mutt_buffer_select_file(BUFFER *f, int flags, 
char ***files, int *numfiles
         else
         {
           char msg[SHORT_STRING];
-          IMAP_MBOX mx;
+          IMAP_MBOX mx = { 0 };
           int nentry = menu->current;
 
           imap_parse_path(state.entry[nentry].full_path, &mx);
           if (!mx.mbox)
           {
+            imap_mbox_free(&mx);
             mutt_error _("Cannot delete root folder");
             break;
           }
@@ -1256,7 +1257,7 @@ void _mutt_buffer_select_file(BUFFER *f, int flags, char 
***files, int *numfiles
           }
           else
             mutt_message _("Mailbox not deleted.");
-          FREE(&mx.mbox);
+          imap_mbox_free(&mx);
         }
         break;
 #endif
diff --git a/imap/browse.c b/imap/browse.c
index 784eef73..22e5c4df 100644
--- a/imap/browse.c
+++ b/imap/browse.c
@@ -53,7 +53,7 @@ int imap_browse(const char *path, struct browser_state *state)
   char ctmp;
   short showparents = 0;
   int save_lsub;
-  IMAP_MBOX mx;
+  IMAP_MBOX mx = { 0 };
 
   if (imap_parse_path(path, &mx))
   {
@@ -218,13 +218,13 @@ int imap_browse(const char *path, struct browser_state 
*state)
   if (save_lsub)
     set_option(OPTIMAPCHECKSUBSCRIBED);
 
-  FREE(&mx.mbox);
+  imap_mbox_free(&mx);
   return 0;
 
 fail:
   if (save_lsub)
     set_option(OPTIMAPCHECKSUBSCRIBED);
-  FREE(&mx.mbox);
+  imap_mbox_free(&mx);
   return -1;
 }
 
@@ -232,7 +232,7 @@ fail:
 int imap_mailbox_create(const char *folder, BUFFER *result)
 {
   IMAP_DATA *idata;
-  IMAP_MBOX mx;
+  IMAP_MBOX mx = { 0 };
   char buf[LONG_STRING];
   short n;
 
@@ -276,18 +276,18 @@ int imap_mailbox_create(const char *folder, BUFFER 
*result)
   mutt_message _("Mailbox created.");
   mutt_sleep(0);
 
-  FREE(&mx.mbox);
+  imap_mbox_free(&mx);
   return 0;
 
 fail:
-  FREE(&mx.mbox);
+  imap_mbox_free(&mx);
   return -1;
 }
 
 int imap_mailbox_rename(const char *mailbox, BUFFER *result)
 {
   IMAP_DATA *idata;
-  IMAP_MBOX mx;
+  IMAP_MBOX mx = { 0 };
   char buf[LONG_STRING];
   char newname[SHORT_STRING];
 
@@ -336,11 +336,11 @@ int imap_mailbox_rename(const char *mailbox, BUFFER 
*result)
   mutt_message(_("Mailbox renamed."));
   mutt_sleep(0);
 
-  FREE(&mx.mbox);
+  imap_mbox_free(&mx);
   return 0;
 
 fail:
-  FREE(&mx.mbox);
+  imap_mbox_free(&mx);
   return -1;
 }
 
@@ -348,7 +348,7 @@ static int browse_add_list_result(IMAP_DATA *idata, const 
char *cmd,
                                   struct browser_state *state, short isparent)
 {
   IMAP_LIST list;
-  IMAP_MBOX mx;
+  IMAP_MBOX mx = { 0 };
   int rc;
 
   if (imap_parse_path(state->folder, &mx))
@@ -379,7 +379,7 @@ static int browse_add_list_result(IMAP_DATA *idata, const 
char *cmd,
   while (rc == IMAP_CMD_CONTINUE);
   idata->cmddata = NULL;
 
-  FREE(&mx.mbox);
+  imap_mbox_free(&mx);
   return rc == IMAP_CMD_OK ? 0 : -1;
 }
 
@@ -394,7 +394,7 @@ static void imap_add_folder(char delim, char *folder, int 
noselect,
 {
   char tmp[LONG_STRING];
   char relpath[LONG_STRING];
-  IMAP_MBOX mx;
+  IMAP_MBOX mx = { 0 };
   BUFFY *b;
 
   if (imap_parse_path(state->folder, &mx))
@@ -467,7 +467,7 @@ static void imap_add_folder(char delim, char *folder, int 
noselect,
 
   (state->entrylen)++;
 
-  FREE(&mx.mbox);
+  imap_mbox_free(&mx);
 }
 
 static int compare_names(struct folder_file *a, struct folder_file *b)
diff --git a/imap/command.c b/imap/command.c
index 77bb7b8f..15839a3f 100644
--- a/imap/command.c
+++ b/imap/command.c
@@ -1120,7 +1120,7 @@ static void cmd_parse_status(IMAP_DATA *idata, char *s)
   char *mailbox;
   char *value;
   BUFFY *inc;
-  IMAP_MBOX mx;
+  IMAP_MBOX mx = { 0 };
   unsigned long ulcount;
   unsigned int count;
   IMAP_STATUS *status;
@@ -1232,7 +1232,7 @@ static void cmd_parse_status(IMAP_DATA *idata, char *s)
       {
         value = safe_strdup(mx.mbox);
         imap_fix_path(idata, mx.mbox, value, mutt_strlen(value) + 1);
-        FREE(&mx.mbox);
+        imap_mbox_free(&mx);
       }
       else
         value = safe_strdup("INBOX");
@@ -1274,6 +1274,7 @@ static void cmd_parse_status(IMAP_DATA *idata, char *s)
              opened */
           status->uidnext = oldun;
 
+        imap_mbox_free(&mx);
         FREE(&value);
         return;
       }
@@ -1281,7 +1282,7 @@ static void cmd_parse_status(IMAP_DATA *idata, char *s)
       FREE(&value);
     }
 
-    FREE(&mx.mbox);
+    imap_mbox_free(&mx);
   }
 }
 
diff --git a/imap/imap.c b/imap/imap.c
index a86a8379..20b80dfc 100644
--- a/imap/imap.c
+++ b/imap/imap.c
@@ -61,7 +61,7 @@ static void imap_set_flag(IMAP_DATA *idata, int aclbit, int 
flag,
 int imap_access(const char *path)
 {
   IMAP_DATA *idata;
-  IMAP_MBOX mx;
+  IMAP_MBOX mx = { 0 };
   char buf[LONG_STRING*2];
   char mailbox[LONG_STRING];
   char mbox[LONG_STRING];
@@ -73,7 +73,7 @@ int imap_access(const char *path)
   if (!(idata = imap_conn_find(&mx.account,
                                option(OPTIMAPPASSIVE) ? MUTT_IMAP_CONN_NONEW : 
0)))
   {
-    FREE(&mx.mbox);
+    imap_mbox_free(&mx);
     return -1;
   }
 
@@ -84,10 +84,10 @@ int imap_access(const char *path)
   /* we may already be in the folder we're checking */
   if (!ascii_strcmp(idata->mailbox, mx.mbox))
   {
-    FREE(&mx.mbox);
+    imap_mbox_free(&mx);
     return 0;
   }
-  FREE(&mx.mbox);
+  imap_mbox_free(&mx);
 
   if (imap_mboxcache_get(idata, mailbox, 0))
   {
@@ -375,7 +375,7 @@ IMAP_DATA *imap_conn_find(const ACCOUNT *account, int flags)
     if (!creds)
       creds = &conn->account;
     else
-      memcpy(&conn->account, creds, sizeof(ACCOUNT));
+      mutt_account_copy(&conn->account, creds);
 
     idata = (IMAP_DATA*)conn->data;
     if (flags & MUTT_IMAP_CONN_NONEW)
@@ -791,7 +791,7 @@ static int imap_open_mailbox(CONTEXT *ctx)
   char buf[LONG_STRING];
   char bufout[LONG_STRING*2];
   int count = 0;
-  IMAP_MBOX mx, pmx;
+  IMAP_MBOX mx = { 0 }, pmx = { 0 };
   int rc;
   const char *condstore;
 
@@ -852,11 +852,10 @@ static int imap_open_mailbox(CONTEXT *ctx)
     mutt_bit_set(idata->ctx->rights, MUTT_ACL_DELETE);
   }
   /* pipeline the postponed count if possible */
-  pmx.mbox = NULL;
   if (mx_is_imap(Postponed) && !imap_parse_path(Postponed, &pmx)
       && mutt_account_match(&pmx.account, &mx.account))
     imap_status(Postponed, 1);
-  FREE(&pmx.mbox);
+  imap_mbox_free(&pmx);
 
 #if USE_HCACHE
   if (mutt_bit_isset(idata->capabilities, CONDSTORE) &&
@@ -1020,14 +1019,14 @@ static int imap_open_mailbox(CONTEXT *ctx)
   imap_disallow_reopen(ctx);
 
   muttdbg(2, "imap_open_mailbox: msgcount is %d", ctx->msgcount);
-  FREE(&mx.mbox);
+  imap_mbox_free(&mx);
   return 0;
 
 fail:
   if (idata->state == IMAP_SELECTED)
     idata->state = IMAP_AUTHENTICATED;
 fail_noidata:
-  FREE(&mx.mbox);
+  imap_mbox_free(&mx);
   return -1;
 }
 
@@ -1036,7 +1035,7 @@ static int imap_open_mailbox_append(CONTEXT *ctx, int 
flags)
   IMAP_DATA *idata;
   char buf[LONG_STRING];
   char mailbox[LONG_STRING];
-  IMAP_MBOX mx;
+  IMAP_MBOX mx = { 0 };
   int rc;
 
   if (imap_parse_path(ctx->path, &mx))
@@ -1047,7 +1046,7 @@ static int imap_open_mailbox_append(CONTEXT *ctx, int 
flags)
 
   if (!(idata = imap_conn_find(&(mx.account), 0)))
   {
-    FREE(&mx.mbox);
+    imap_mbox_free(&mx);
     return -1;
   }
 
@@ -1056,7 +1055,7 @@ static int imap_open_mailbox_append(CONTEXT *ctx, int 
flags)
   imap_fix_path(idata, mx.mbox, mailbox, sizeof(mailbox));
   if (!*mailbox)
     strfcpy(mailbox, "INBOX", sizeof(mailbox));
-  FREE(&mx.mbox);
+  imap_mbox_free(&mx);
 
   if ((rc = imap_access(ctx->path)) == 0)
     return 0;
@@ -1861,7 +1860,7 @@ static int imap_save_to_header_cache(CONTEXT *ctx, HEADER 
*h)
 /* split path into (idata,mailbox name) */
 static int imap_get_mailbox(const char *path, IMAP_DATA **hidata, char *buf, 
size_t blen)
 {
-  IMAP_MBOX mx;
+  IMAP_MBOX mx = { 0 };
 
   if (imap_parse_path(path, &mx))
   {
@@ -1870,14 +1869,14 @@ static int imap_get_mailbox(const char *path, IMAP_DATA 
**hidata, char *buf, siz
   }
   if (!(*hidata = imap_conn_find(&(mx.account), option(OPTIMAPPASSIVE) ? 
MUTT_IMAP_CONN_NONEW : 0)))
   {
-    FREE(&mx.mbox);
+    imap_mbox_free(&mx);
     return -1;
   }
 
   imap_fix_path(*hidata, mx.mbox, buf, blen);
   if (!*buf)
     strfcpy(buf, "INBOX", blen);
-  FREE(&mx.mbox);
+  imap_mbox_free(&mx);
 
   return 0;
 }
@@ -2270,10 +2269,11 @@ int imap_subscribe(char *path, int subscribe)
   IMAP_DATA *idata;
   char buf[LONG_STRING*2];
   char mbox[LONG_STRING];
-  IMAP_MBOX mx;
+  IMAP_MBOX mx = { 0 };
 
   if (!mx_is_imap(path) || imap_parse_path(path, &mx) || !mx.mbox)
   {
+    imap_mbox_free(&mx);
     mutt_error(_("Bad mailbox name"));
     return -1;
   }
@@ -2308,11 +2308,11 @@ int imap_subscribe(char *path, int subscribe)
     mutt_message(_("Subscribed to %s"), mx.mbox);
   else
     mutt_message(_("Unsubscribed from %s"), mx.mbox);
-  FREE(&mx.mbox);
+  imap_mbox_free(&mx);
   return 0;
 
 fail:
-  FREE(&mx.mbox);
+  imap_mbox_free(&mx);
   return -1;
 }
 
@@ -2395,7 +2395,7 @@ int imap_complete(char *dest, size_t dlen, const char 
*path)
   size_t clen;
   size_t matchlen = 0;
   int completions = 0;
-  IMAP_MBOX mx;
+  IMAP_MBOX mx = { 0 };
   int rc;
 
   if (imap_parse_path(path, &mx))
@@ -2408,7 +2408,7 @@ int imap_complete(char *dest, size_t dlen, const char 
*path)
    * known mailboxes/hooks/etc */
   if (!(idata = imap_conn_find(&(mx.account), MUTT_IMAP_CONN_NONEW)))
   {
-    FREE(&mx.mbox);
+    imap_mbox_free(&mx);
     strfcpy(dest, path, dlen);
     return imap_complete_hosts(dest, dlen);
   }
@@ -2467,11 +2467,11 @@ int imap_complete(char *dest, size_t dlen, const char 
*path)
     imap_qualify_path(dest, dlen, &mx, completion);
     mutt_pretty_mailbox(dest, dlen);
 
-    FREE(&mx.mbox);
+    imap_mbox_free(&mx);
     return 0;
   }
 
-  FREE(&mx.mbox);
+  imap_mbox_free(&mx);
   return -1;
 }
 
@@ -2488,7 +2488,7 @@ int imap_fast_trash(CONTEXT *ctx, char *dest)
   char mmbox[LONG_STRING];
   char prompt[LONG_STRING];
   int n, rc;
-  IMAP_MBOX mx;
+  IMAP_MBOX mx = { 0 };
   int triedcreate = 0;
   BUFFER *sync_cmd = NULL;
   int err_continue = MUTT_NO;
@@ -2505,7 +2505,7 @@ int imap_fast_trash(CONTEXT *ctx, char *dest)
   if (!mutt_account_match(&(CTX_DATA->conn->account), &(mx.account)))
   {
     muttdbg(3, "%s not same server as %s", dest, ctx->path);
-    FREE(&mx.mbox);
+    imap_mbox_free(&mx);
     return 1;
   }
 
@@ -2602,7 +2602,7 @@ int imap_fast_trash(CONTEXT *ctx, char *dest)
 
 out:
   mutt_buffer_free(&sync_cmd);
-  FREE(&mx.mbox);
+  imap_mbox_free(&mx);
 
   return rc < 0 ? -1 : rc;
 }
diff --git a/imap/imap.h b/imap/imap.h
index f2035e89..efb64cb2 100644
--- a/imap/imap.h
+++ b/imap/imap.h
@@ -65,6 +65,7 @@ void imap_logout_all(void);
 int imap_expand_path(BUFFER *path);
 int imap_buffer_remove_path_password(BUFFER *dest, const char *src);
 int imap_parse_path(const char *path, IMAP_MBOX *mx);
+void imap_mbox_free(IMAP_MBOX *mbox);
 void imap_pretty_mailbox(char *path, size_t pathlen);
 
 int imap_wait_keepalive(pid_t pid);
diff --git a/imap/message.c b/imap/message.c
index 1924ab21..006ae861 100644
--- a/imap/message.c
+++ b/imap/message.c
@@ -1323,7 +1323,7 @@ int imap_append_message(CONTEXT *ctx, MESSAGE *msg)
   progress_t progressbar;
   size_t sent;
   int c, last;
-  IMAP_MBOX mx;
+  IMAP_MBOX mx = { 0 };
   int rc;
 
   idata = (IMAP_DATA*) ctx->data;
@@ -1422,7 +1422,7 @@ int imap_append_message(CONTEXT *ctx, MESSAGE *msg)
   if (rc != IMAP_CMD_OK)
     goto cmd_step_fail;
 
-  FREE(&mx.mbox);
+  imap_mbox_free(&mx);
   return 0;
 
 cmd_step_fail:
@@ -1442,7 +1442,7 @@ cmd_step_fail:
 
 fail:
   safe_fclose(&fp);
-  FREE(&mx.mbox);
+  imap_mbox_free(&mx);
   return -1;
 }
 
@@ -1461,7 +1461,7 @@ int imap_copy_messages(CONTEXT *ctx, HEADER *h, const 
char *dest, int delete)
   char prompt[LONG_STRING];
   int rc;
   int n;
-  IMAP_MBOX mx;
+  IMAP_MBOX mx = { 0 };
   int err_continue = MUTT_NO;
   int triedcreate = 0;
 
@@ -1626,7 +1626,7 @@ int imap_copy_messages(CONTEXT *ctx, HEADER *h, const 
char *dest, int delete)
 out:
   mutt_buffer_pool_release(&sync_cmd);
   mutt_buffer_pool_release(&cmd);
-  FREE(&mx.mbox);
+  imap_mbox_free(&mx);
 
   return rc < 0 ? -1 : rc;
 }
diff --git a/imap/util.c b/imap/util.c
index 6b9940b7..4c877f8d 100644
--- a/imap/util.c
+++ b/imap/util.c
@@ -51,7 +51,7 @@
  *   fails, which it might if there isn't enough room in the buffer. */
 int imap_expand_path(BUFFER *path)
 {
-  IMAP_MBOX mx;
+  IMAP_MBOX mx = { 0 };
   IMAP_DATA *idata;
   ciss_url_t url;
   char fixedpath[LONG_STRING];
@@ -66,14 +66,14 @@ int imap_expand_path(BUFFER *path)
   url.path = fixedpath;
 
   rc = url_ciss_tobuffer(&url, path, U_DECODE_PASSWD);
-  FREE(&mx.mbox);
+  imap_mbox_free(&mx);
 
   return rc;
 }
 
 int imap_buffer_remove_path_password(BUFFER *dest, const char *src)
 {
-  IMAP_MBOX mx;
+  IMAP_MBOX mx = { 0 };
   ciss_url_t url;
   int rc;
 
@@ -87,7 +87,7 @@ int imap_buffer_remove_path_password(BUFFER *dest, const char 
*src)
 
   /* flags = 0 will strip the password, if present */
   rc = url_ciss_tobuffer(&url, dest, 0);
-  FREE(&mx.mbox);
+  imap_mbox_free(&mx);
 
   return rc;
 }
@@ -158,7 +158,7 @@ static void imap_hcache_namer(const char *path, BUFFER 
*dest)
 
 header_cache_t *imap_hcache_open(IMAP_DATA *idata, const char *path)
 {
-  IMAP_MBOX mx;
+  IMAP_MBOX mx = { 0 };
   ciss_url_t url;
   BUFFER *cachepath = NULL;
   BUFFER *mbox = NULL;
@@ -176,7 +176,6 @@ header_cache_t *imap_hcache_open(IMAP_DATA *idata, const 
char *path)
       goto cleanup;
 
     imap_cachepath(idata, mx.mbox, mbox);
-    FREE(&mx.mbox);
   }
 
   if (strstr(mutt_b2s(mbox), "/../") ||
@@ -195,6 +194,7 @@ header_cache_t *imap_hcache_open(IMAP_DATA *idata, const 
char *path)
   rv = mutt_hcache_open(HeaderCache, mutt_b2s(cachepath), imap_hcache_namer);
 
 cleanup:
+  imap_mbox_free(&mx);
   mutt_buffer_pool_release(&mbox);
   mutt_buffer_pool_release(&cachepath);
   return rv;
@@ -321,7 +321,7 @@ int imap_parse_path(const char *path, IMAP_MBOX *mx)
   static unsigned short ImapPort = 0;
   static unsigned short ImapsPort = 0;
   struct servent *service;
-  char tmp[128];
+  char tmp[128], tmp2[128];
   ciss_url_t url;
   char *c;
   const char *constc;
@@ -355,8 +355,9 @@ int imap_parse_path(const char *path, IMAP_MBOX *mx)
   url_parse_ciss(&url, c);
   if (url.scheme == U_IMAP || url.scheme == U_IMAPS)
   {
-    if (mutt_account_fromurl(&mx->account, &url) < 0 || !*mx->account.host)
+    if (mutt_account_fromurl(&mx->account, &url) < 0 || !mx->account.host)
     {
+      mutt_account_free(&mx->account);
       FREE(&c);
       return -1;
     }
@@ -385,18 +386,19 @@ int imap_parse_path(const char *path, IMAP_MBOX *mx)
     if ((c = strrchr(tmp, '@')))
     {
       *c = '\0';
-      strfcpy(mx->account.user, tmp, sizeof(mx->account.user));
+      mx->account.user = safe_strdup(tmp);
       strfcpy(tmp, c+1, sizeof(tmp));
       mx->account.flags |= MUTT_ACCT_USER;
       mx->account.flags |= MUTT_ACCT_USER_FROM_URL;
     }
 
-    if ((n = sscanf(tmp, "%127[^:/]%127s", mx->account.host, tmp)) < 1)
+    if ((n = sscanf(tmp, "%127[^:/]%127s", tmp2, tmp)) < 1)
     {
       muttdbg(1, "imap_parse_path: NULL host in %s", path);
-      FREE(&mx->mbox);
+      imap_mbox_free(mx);
       return -1;
     }
+    mx->account.host = safe_strdup(tmp2);
 
     if (n > 1)
     {
@@ -409,7 +411,7 @@ int imap_parse_path(const char *path, IMAP_MBOX *mx)
         else
         {
           muttdbg(1, "imap_parse_path: Unknown connection type in %s", path);
-          FREE(&mx->mbox);
+          imap_mbox_free(mx);
           return -1;
         }
       }
@@ -422,6 +424,16 @@ int imap_parse_path(const char *path, IMAP_MBOX *mx)
   return 0;
 }
 
+/* The IMAP_MBOX structures aren't dynamically allocated, but its members are. 
*/
+void imap_mbox_free(IMAP_MBOX *mbox)
+{
+  if (!mbox)
+    return;
+
+  mutt_account_free(&mbox->account);
+  FREE(&mbox->mbox);
+}
+
 /* silly helper for mailbox name string comparisons, because of INBOX */
 int imap_mxcmp(const char *mx1, const char *mx2)
 {
@@ -453,7 +465,7 @@ int imap_mxcmp(const char *mx1, const char *mx2)
  *   look nice. */
 void imap_pretty_mailbox(char *path, size_t pathlen)
 {
-  IMAP_MBOX home, target;
+  IMAP_MBOX home = { 0 }, target = { 0 };
   ciss_url_t url;
   char *delim;
   int tlen;
@@ -478,7 +490,6 @@ void imap_pretty_mailbox(char *path, size_t pathlen)
           if (target.mbox[hlen] == *delim)
             home_match = 1;
     }
-    FREE(&home.mbox);
   }
 
   /* do the '=' substitution */
@@ -498,7 +509,8 @@ void imap_pretty_mailbox(char *path, size_t pathlen)
     url_ciss_tostring(&url, path, pathlen, 0);
   }
 
-  FREE(&target.mbox);
+  imap_mbox_free(&home);
+  imap_mbox_free(&target);
 }
 
 /* -- library functions -- */
diff --git a/mutt_socket.c b/mutt_socket.c
index 79314fe9..5065bbdd 100644
--- a/mutt_socket.c
+++ b/mutt_socket.c
@@ -276,6 +276,7 @@ void mutt_socket_free(CONNECTION *conn)
   if (iter == conn)
   {
     Connections = iter->next;
+    mutt_account_free(&iter->account);
     FREE(&iter);
     return;
   }
@@ -286,6 +287,7 @@ void mutt_socket_free(CONNECTION *conn)
     {
       tmp = iter->next;
       iter->next = tmp->next;
+      mutt_account_free(&tmp->account);
       FREE(&tmp);
       return;
     }
@@ -319,7 +321,7 @@ CONNECTION *mutt_conn_find(const CONNECTION *start, const 
ACCOUNT *account)
   }
 
   conn = socket_new_conn();
-  memcpy(&conn->account, account, sizeof(ACCOUNT));
+  mutt_account_copy(&conn->account, account);
 
   conn->next = Connections;
   Connections = conn;
diff --git a/pop_auth.c b/pop_auth.c
index d22038d2..e3072fbd 100644
--- a/pop_auth.c
+++ b/pop_auth.c
@@ -352,7 +352,7 @@ static pop_auth_res_t pop_auth_apop(POP_DATA *pop_data, 
const char *method)
   md5_init_ctx(&ctx);
   md5_process_bytes(pop_data->timestamp, strlen(pop_data->timestamp), &ctx);
   md5_process_bytes(pop_data->conn->account.pass,
-                    strlen(pop_data->conn->account.pass), &ctx);
+                    mutt_strlen(pop_data->conn->account.pass), &ctx);
   md5_finish_ctx(&ctx, digest);
 
   for (i = 0; i < sizeof(digest); i++)
-- 
2.55.0

Reply via email to