changeset: 6516:ac156dcc2c54 user: Kevin McCarthy <ke...@8t8.us> date: Sun Oct 04 10:08:45 2015 +0800 link: http://dev.mutt.org/hg/mutt/rev/ac156dcc2c54
Fix menu type in certificate prompt. (see #3779) The menu type is used in several places as a direct index into Keymaps[], so passing in -1 to mutt_new_menu() was leading to illegal memory accesses later on. Add a range check in mutt_new_menu(), defaulting to MENU_GENERIC, to prevent this problem in the future. changeset: 6517:a07e8215a0ef user: Kevin McCarthy <ke...@8t8.us> date: Sun Oct 04 10:08:49 2015 +0800 link: http://dev.mutt.org/hg/mutt/rev/a07e8215a0ef Create a separate macro/push/exec event buffer. (closes #3779) Currently, the SSL and TLS certficate prompts turn on OPTUNBUFFEREDINPUT, (to prevent macros and such from running right through the dialog). Unfortunately, the menu dialog processing in menu_dialog_dokey() is using mutt_ungetch() to forward non-dialog keys on to standard menu processing. With OPTUNBUFFEREDINPUT set, those keys never make it to the menu and are buffered until after the menu dialog. This patch creates a new event buffer, separate from the standard "unget" buffer, for use by macros, exec, and push events. These events can be temporarily ignored by setting OPTIGNOREMACROEVENTS (renamed from OPTUNBUFFEREDINPUT), while continuing to allow unget events to be processed. Since the "push" and "unget" functions now go to different buffers, function names were slightly renamed, to make it less easy to unintentionally use the wrong function at the wrong time. diffs (473 lines): diff -r 9de2f1c6da87 -r a07e8215a0ef browser.c --- a/browser.c Thu Oct 01 15:38:47 2015 +0800 +++ b/browser.c Sun Oct 04 10:08:49 2015 +0800 @@ -896,7 +896,7 @@ else set_option (OPTIMAPLSUB); - mutt_ungetch (0, OP_CHECK_NEW); + mutt_unget_event (0, OP_CHECK_NEW); break; case OP_CREATE_MAILBOX: diff -r 9de2f1c6da87 -r a07e8215a0ef commands.c --- a/commands.c Thu Oct 01 15:38:47 2015 +0800 +++ b/commands.c Sun Oct 04 10:08:49 2015 +0800 @@ -228,7 +228,7 @@ mutt_set_flag (Context, cur, M_READ, 1); if (r != -1 && option (OPTPROMPTAFTER)) { - mutt_ungetch (mutt_any_key_to_continue _("Command: "), 0); + mutt_unget_event (mutt_any_key_to_continue _("Command: "), 0); rc = km_dokey (MENU_PAGER); } else diff -r 9de2f1c6da87 -r a07e8215a0ef curs_lib.c --- a/curs_lib.c Thu Oct 01 15:38:47 2015 +0800 +++ b/curs_lib.c Sun Oct 04 10:08:49 2015 +0800 @@ -48,9 +48,20 @@ * is impossible to unget function keys in SLang, so roll our own input * buffering routines. */ -size_t UngetCount = 0; -static size_t UngetBufLen = 0; -static event_t *KeyEvent; + +/* These are used for macros and exec/push commands. + * They can be temporarily ignored by setting OPTIGNOREMACROEVENTS + */ +static size_t MacroBufferCount = 0; +static size_t MacroBufferLen = 0; +static event_t *MacroEvents; + +/* These are used in all other "normal" situations, and are not + * ignored when setting OPTIGNOREMACROEVENTS + */ +static size_t UngetCount = 0; +static size_t UngetLen = 0; +static event_t *UngetKeyEvents; void mutt_refresh (void) { @@ -83,8 +94,11 @@ event_t err = {-1, OP_NULL }, ret; event_t timeout = {-2, OP_NULL}; - if (!option(OPTUNBUFFEREDINPUT) && UngetCount) - return (KeyEvent[--UngetCount]); + if (UngetCount) + return (UngetKeyEvents[--UngetCount]); + + if (!option(OPTIGNOREMACROEVENTS) && MacroBufferCount) + return (MacroEvents[--MacroBufferCount]); SigInt = 0; @@ -118,7 +132,7 @@ { /* send ALT-x as ESC-x */ ch &= ~0x80; - mutt_ungetch (ch, 0); + mutt_unget_event (ch, 0); ret.ch = '\033'; ret.op = 0; return ret; @@ -157,9 +171,9 @@ { int rc; - set_option (OPTUNBUFFEREDINPUT); + set_option (OPTIGNOREMACROEVENTS); rc = mutt_get_field (msg, buf, buflen, flags); - unset_option (OPTUNBUFFEREDINPUT); + unset_option (OPTIGNOREMACROEVENTS); return (rc); } @@ -595,7 +609,7 @@ char *pc = safe_malloc (mutt_strlen (prompt) + 3); sprintf (pc, "%s: ", prompt); /* __SPRINTF_CHECKED__ */ - mutt_ungetch (ch.op ? 0 : ch.ch, ch.op ? ch.op : 0); + mutt_unget_event (ch.op ? 0 : ch.ch, ch.op ? ch.op : 0); if (_mutt_get_field (pc, buf, blen, (buffy ? M_EFILE : M_FILE) | M_CLEAR, multiple, files, numfiles) != 0) buf[0] = 0; @@ -606,22 +620,60 @@ return 0; } -void mutt_ungetch (int ch, int op) +void mutt_unget_event (int ch, int op) { event_t tmp; tmp.ch = ch; tmp.op = op; - if (UngetCount >= UngetBufLen) - safe_realloc (&KeyEvent, (UngetBufLen += 128) * sizeof(event_t)); + if (UngetCount >= UngetLen) + safe_realloc (&UngetKeyEvents, (UngetLen += 16) * sizeof(event_t)); - KeyEvent[UngetCount++] = tmp; + UngetKeyEvents[UngetCount++] = tmp; +} + +void mutt_unget_string (char *s) +{ + char *p = s + mutt_strlen (s) - 1; + + while (p >= s) + { + mutt_unget_event ((unsigned char)*p--, 0); + } +} + +/* + * Adds the ch/op to the macro buffer. + * This should be used for macros, push, and exec commands only. + */ +void mutt_push_macro_event (int ch, int op) +{ + event_t tmp; + + tmp.ch = ch; + tmp.op = op; + + if (MacroBufferCount >= MacroBufferLen) + safe_realloc (&MacroEvents, (MacroBufferLen += 128) * sizeof(event_t)); + + MacroEvents[MacroBufferCount++] = tmp; +} + +void mutt_flush_macro_to_endcond (void) +{ + UngetCount = 0; + while (MacroBufferCount > 0) + { + if (MacroEvents[--MacroBufferCount].op == OP_END_COND) + return; + } } void mutt_flushinp (void) { UngetCount = 0; + MacroBufferCount = 0; flushinp (); } diff -r 9de2f1c6da87 -r a07e8215a0ef curs_main.c --- a/curs_main.c Thu Oct 01 15:38:47 2015 +0800 +++ b/curs_main.c Sun Oct 04 10:08:49 2015 +0800 @@ -109,8 +109,6 @@ #define OLDHDR Context->hdrs[Context->v2r[menu->oldcurrent]] #define UNREAD(h) mutt_thread_contains_unread (Context, h) -extern size_t UngetCount; - /* de facto standard escapes for tsl/fsl */ static char *tsl = "\033]0;"; static char *fsl = "\007"; @@ -729,12 +727,7 @@ if (!Context->tagged) { - event_t tmp; - while(UngetCount>0) - { - tmp=mutt_getch(); - if(tmp.op==OP_END_COND)break; - } + mutt_flush_macro_to_endcond (); mutt_message _("Nothing to do."); continue; } @@ -819,7 +812,7 @@ CHECK_MSGCOUNT; CHECK_VISIBLE; - if (isdigit (LastKey)) mutt_ungetch (LastKey, 0); + if (isdigit (LastKey)) mutt_unget_event (LastKey, 0); buf[0] = 0; if (mutt_get_field (_("Jump to message: "), buf, sizeof (buf), 0) != 0 || !buf[0]) diff -r 9de2f1c6da87 -r a07e8215a0ef keymap.c --- a/keymap.c Thu Oct 01 15:38:47 2015 +0800 +++ b/keymap.c Sun Oct 04 10:08:49 2015 +0800 @@ -325,7 +325,12 @@ return NULL; } -static void push_string (char *s) +/* Parses s for <function> syntax and adds the whole sequence to + * the macro buffer. + * + * This should be used for macros, push, and exec commands only. + */ +static void tokenize_push_macro_string (char *s) { char *pp, *p = s + mutt_strlen (s) - 1; size_t l; @@ -343,7 +348,7 @@ { if ((i = parse_fkey (pp)) > 0) { - mutt_ungetch (KEY_F (i), 0); + mutt_push_macro_event (KEY_F (i), 0); p = pp - 1; continue; } @@ -357,7 +362,7 @@ if (KeyNames[i].name) { /* found a match */ - mutt_ungetch (KeyNames[i].value, 0); + mutt_push_macro_event (KeyNames[i].value, 0); p = pp - 1; continue; } @@ -377,13 +382,13 @@ if (op != OP_NULL) { - mutt_ungetch (0, op); + mutt_push_macro_event (0, op); p = pp - 1; continue; } } } - mutt_ungetch ((unsigned char)*p--, 0); /* independent 8 bits chars */ + mutt_push_macro_event ((unsigned char)*p--, 0); /* independent 8 bits chars */ } } @@ -392,9 +397,9 @@ if (menu != MENU_EDITOR && menu != MENU_GENERIC && menu != MENU_PAGER) { if (lastkey) - mutt_ungetch (lastkey, 0); + mutt_unget_event (lastkey, 0); for (; keyslen; keyslen--) - mutt_ungetch (keys[keyslen - 1], 0); + mutt_unget_event (keys[keyslen - 1], 0); return (km_dokey (MENU_GENERIC)); } if (menu != MENU_EDITOR) @@ -495,11 +500,9 @@ func = get_func (bindings, tmp.op); if (func) { - /* careful not to feed the <..> as one token. otherwise - * push_string() will push the bogus op right back! */ - mutt_ungetch ('>', 0); - push_string (func); - mutt_ungetch ('<', 0); + mutt_unget_event ('>', 0); + mutt_unget_string (func); + mutt_unget_event ('<', 0); break; } } @@ -526,6 +529,12 @@ if (map->op != OP_MACRO) return map->op; + if (option (OPTIGNOREMACROEVENTS)) + { + mutt_error _("Macros are currently disabled."); + return -1; + } + if (n++ == 10) { mutt_flushinp (); @@ -533,7 +542,7 @@ return -1; } - push_string (map->macro); + tokenize_push_macro_string (map->macro); map = Keymaps[menu]; pos = 0; } @@ -835,7 +844,7 @@ } /* make sure the key is really the help key in this menu */ - push_string (buf); + mutt_unget_string (buf); if (km_dokey (menu) != OP_HELP) { mutt_error _("Key is not bound."); @@ -857,7 +866,7 @@ r = -1; } else - push_string (buf->data); + tokenize_push_macro_string (buf->data); return (r); } @@ -1107,7 +1116,7 @@ while(MoreArgs(s) && nops < sizeof(ops)/sizeof(ops[0])); while(nops) - mutt_ungetch(0, ops[--nops]); + mutt_push_macro_event (0, ops[--nops]); return 0; } diff -r 9de2f1c6da87 -r a07e8215a0ef menu.c --- a/menu.c Thu Oct 01 15:38:47 2015 +0800 +++ b/menu.c Sun Oct 04 10:08:49 2015 +0800 @@ -25,8 +25,6 @@ #include "mutt_menu.h" #include "mbyte.h" -extern size_t UngetCount; - char* SearchBuffers[MENU_MAX]; static void print_enriched_string (int attr, unsigned char *s, int do_color) @@ -415,7 +413,7 @@ if (menu->max) { - mutt_ungetch (LastKey, 0); + mutt_unget_event (LastKey, 0); buf[0] = 0; if (mutt_get_field (_("Jump to: "), buf, sizeof (buf), 0) == 0 && buf[0]) { @@ -684,6 +682,9 @@ { MUTTMENU *p = (MUTTMENU *) safe_calloc (1, sizeof (MUTTMENU)); + if ((menu < 0) || (menu >= MENU_MAX)) + menu = MENU_GENERIC; + p->menu = menu; p->current = 0; p->top = 0; @@ -814,7 +815,7 @@ } else { - mutt_ungetch (ch.op ? 0 : ch.ch, ch.op ? ch.op : 0); + mutt_unget_event (ch.op ? 0 : ch.ch, ch.op ? ch.op : 0); return -1; } } @@ -902,12 +903,7 @@ } else /* None tagged, OP_TAG_PREFIX_COND */ { - event_t tmp; - while(UngetCount>0) - { - tmp=mutt_getch(); - if(tmp.op==OP_END_COND)break; - } + mutt_flush_macro_to_endcond (); mutt_message _("Nothing to do."); i = -1; } diff -r 9de2f1c6da87 -r a07e8215a0ef mutt.h --- a/mutt.h Thu Oct 01 15:38:47 2015 +0800 +++ b/mutt.h Sun Oct 04 10:08:49 2015 +0800 @@ -98,9 +98,6 @@ #define M_TOKEN_COMMENT (1<<5) /* don't reap comments */ #define M_TOKEN_SEMICOLON (1<<6) /* don't treat ; as special */ -/* flags for km_dokey() */ -#define M_KM_UNBUFFERED 1 /* don't read from the key buffer */ - typedef struct { char *data; /* pointer to data */ @@ -513,7 +510,7 @@ OPTREDRAWTREE, /* (pseudo) redraw the thread tree */ OPTPGPCHECKTRUST, /* (pseudo) used by pgp_select_key () */ OPTDONTHANDLEPGPKEYS, /* (pseudo) used to extract PGP keys */ - OPTUNBUFFEREDINPUT, /* (pseudo) don't use key buffer */ + OPTIGNOREMACROEVENTS, /* (pseudo) don't process macro/push/exec events while set */ OPTMAX }; diff -r 9de2f1c6da87 -r a07e8215a0ef mutt_curses.h --- a/mutt_curses.h Thu Oct 01 15:38:47 2015 +0800 +++ b/mutt_curses.h Sun Oct 04 10:08:49 2015 +0800 @@ -93,7 +93,10 @@ void mutt_flushinp (void); void mutt_refresh (void); void mutt_resize_screen (void); -void mutt_ungetch (int, int); +void mutt_unget_event (int, int); +void mutt_unget_string (char *); +void mutt_push_macro_event (int, int); +void mutt_flush_macro_to_endcond (void); void mutt_need_hard_redraw (void); /* ---------------------------------------------------------------------------- diff -r 9de2f1c6da87 -r a07e8215a0ef mutt_ssl.c --- a/mutt_ssl.c Thu Oct 01 15:38:47 2015 +0800 +++ b/mutt_ssl.c Sun Oct 04 10:08:49 2015 +0800 @@ -977,7 +977,7 @@ char helpstr[LONG_STRING]; char buf[STRING]; char title[STRING]; - MUTTMENU *menu = mutt_new_menu (-1); + MUTTMENU *menu = mutt_new_menu (MENU_GENERIC); int done, row, i; FILE *fp; char *name = NULL, *c; @@ -1051,7 +1051,7 @@ menu->help = helpstr; done = 0; - set_option(OPTUNBUFFEREDINPUT); + set_option(OPTIGNOREMACROEVENTS); while (!done) { switch (mutt_menuLoop (menu)) @@ -1086,7 +1086,7 @@ break; } } - unset_option(OPTUNBUFFEREDINPUT); + unset_option(OPTIGNOREMACROEVENTS); mutt_menuDestroy (&menu); dprint (2, (debugfile, "ssl interactive_check_cert: done=%d\n", done)); return (done == 2); diff -r 9de2f1c6da87 -r a07e8215a0ef mutt_ssl_gnutls.c --- a/mutt_ssl_gnutls.c Thu Oct 01 15:38:47 2015 +0800 +++ b/mutt_ssl_gnutls.c Sun Oct 04 10:08:49 2015 +0800 @@ -850,7 +850,7 @@ return 0; } - menu = mutt_new_menu (-1); + menu = mutt_new_menu (MENU_GENERIC); menu->max = 25; menu->dialog = (char **) safe_calloc (1, menu->max * sizeof (char *)); for (i = 0; i < menu->max; i++) @@ -1005,7 +1005,7 @@ menu->help = helpstr; done = 0; - set_option (OPTUNBUFFEREDINPUT); + set_option (OPTIGNOREMACROEVENTS); while (!done) { switch (mutt_menuLoop (menu)) @@ -1057,7 +1057,7 @@ break; } } - unset_option (OPTUNBUFFEREDINPUT); + unset_option (OPTIGNOREMACROEVENTS); mutt_menuDestroy (&menu); gnutls_x509_crt_deinit (cert);