mutt stable branch with some hacks
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Fix imap postponed mailbox use-after-free error.

mutt_get_postponed() was calling mx_close_mailbox(), but not checking
the return value. Because the postponed context is an actual
read-write, selected mailbox in a new connection, a failed close left
a dangling pointer in connection->idata->ctx.

imap_keepalive() traversed the connection list, finding the Postponed
connection still there, and passed the dangling pointer to
imap_check_mailbox.

Change an empty postponed mailbox to just call fastclose. Change the
other closes to retry on a postive return code "reopen" event and then
finally just call fastclose.

Outside the index and postponed menu, Mutt's code only uses append or
readonly temporary contexts. Those are guaranteed to call
mx_fastclose_mailbox() and return 0.

+29 -4
+15 -1
mx.c
··· 829 829 return 0; 830 830 } 831 831 832 - /* save changes and close mailbox */ 832 + /* save changes and close mailbox. 833 + * 834 + * returns 0 on success. 835 + * -1 on error 836 + * one of the check_mailbox enums if aborted for one of those reasons. 837 + * 838 + * Note: it's very important to ensure the mailbox is properly closed 839 + * before free'ing the context. For selected mailboxes, IMAP 840 + * will cache the context inside connection->idata until 841 + * imap_close_mailbox() removes it. 842 + * 843 + * Readonly, dontwrite, and append mailboxes are guaranteed to call 844 + * mx_fastclose_mailbox(), so for most of Mutt's code you won't see 845 + * return value checks for temporary contexts. 846 + */ 833 847 int mx_close_mailbox (CONTEXT *ctx, int *index_hint) 834 848 { 835 849 int i, move_messages = 0, purge = 1, read_msgs = 0;
+14 -3
postpone.c
··· 242 242 LIST *next; 243 243 const char *p; 244 244 int opt_delete; 245 + int close_rc; 245 246 246 247 if (!Postponed) 247 248 return (-1); ··· 256 257 if (! PostContext->msgcount) 257 258 { 258 259 PostCount = 0; 259 - mx_close_mailbox (PostContext, NULL); 260 + mx_fastclose_mailbox (PostContext); 260 261 FREE (&PostContext); 261 262 mutt_error _("No postponed messages."); 262 263 return (-1); ··· 269 270 } 270 271 else if ((h = select_msg ()) == NULL) 271 272 { 272 - mx_close_mailbox (PostContext, NULL); 273 + /* messages might have been marked for deletion. 274 + * try once more on reopen before giving up. */ 275 + close_rc = mx_close_mailbox (PostContext, NULL); 276 + if (close_rc > 0) 277 + close_rc = mx_close_mailbox (PostContext, NULL); 278 + if (close_rc != 0) 279 + mx_fastclose_mailbox (PostContext); 273 280 FREE (&PostContext); 274 281 return (-1); 275 282 } ··· 291 298 /* avoid the "purge deleted messages" prompt */ 292 299 opt_delete = quadoption (OPT_DELETE); 293 300 set_quadoption (OPT_DELETE, MUTT_YES); 294 - mx_close_mailbox (PostContext, NULL); 301 + close_rc = mx_close_mailbox (PostContext, NULL); 302 + if (close_rc > 0) 303 + close_rc = mx_close_mailbox (PostContext, NULL); 304 + if (close_rc != 0) 305 + mx_fastclose_mailbox (PostContext); 295 306 set_quadoption (OPT_DELETE, opt_delete); 296 307 297 308 FREE (&PostContext);