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);
 

Reply via email to