Patch 8.1.0439
Problem:    Recursive use of getcmdline() still not protected.
Solution:   Instead of saving the command buffer when making a call which may
            cause recursiveness, save the buffer when actually being called
            recursively.
Files:      src/ex_getln.c, src/proto/ex_getln.pro, src/getchar.c, src/main.c


*** ../vim-8.1.0438/src/ex_getln.c      2018-09-25 22:27:31.958075001 +0200
--- src/ex_getln.c      2018-09-30 17:09:47.106527162 +0200
***************
*** 44,56 ****
  # endif
  };
  
! /* The current cmdline_info.  It is initialized in getcmdline() and after that
!  * used by other functions.  When invoking getcmdline() recursively it needs
!  * to be saved with save_cmdline() and restored with restore_cmdline().
!  * TODO: make it local to getcmdline() and pass it around. */
  static struct cmdline_info ccline;
  
! static int    cmd_showtail;           /* Only show path tail in lists ? */
  
  #ifdef FEAT_EVAL
  static int    new_cmdpos;     /* position set by set_cmdline_pos() */
--- 44,55 ----
  # endif
  };
  
! // The current cmdline_info.  It is initialized in getcmdline() and after that
! // used by other functions.  When invoking getcmdline() recursively it needs
! // to be saved with save_cmdline() and restored with restore_cmdline().
  static struct cmdline_info ccline;
  
! static int    cmd_showtail;   /* Only show path tail in lists ? */
  
  #ifdef FEAT_EVAL
  static int    new_cmdpos;     /* position set by set_cmdline_pos() */
***************
*** 91,96 ****
--- 90,96 ----
  static int    cmd_fkmap = 0;  /* Farsi mapping during command line */
  #endif
  
+ static char_u *getcmdline_int(int firstc, long count, int indent, int 
init_ccline);
  static int    cmdline_charsize(int idx);
  static void   set_cmdspos(void);
  static void   set_cmdspos_cursor(void);
***************
*** 463,469 ****
      int               skiplen, patlen;
      int               found;  // do_search() result
      pos_T     end_pos;
-     struct cmdline_info       save_ccline;
  #ifdef FEAT_RELTIME
      proftime_T        tm;
  #endif
--- 463,468 ----
***************
*** 601,609 ****
      if (p_ru && curwin->w_status_height > 0)
        curwin->w_redr_status = TRUE;
  
-     save_cmdline(&save_ccline);
      update_screen(SOME_VALID);
-     restore_cmdline(&save_ccline);
      restore_last_search_pattern();
  
      // Leave it at the end to make CTRL-R CTRL-W work.  But not when beyond 
the
--- 600,606 ----
***************
*** 800,807 ****
      char_u *
  getcmdline(
      int               firstc,
!     long      count UNUSED,   /* only used for incremental search */
!     int               indent)         /* indent for inside conditionals */
  {
      int               c;
      int               i;
--- 797,814 ----
      char_u *
  getcmdline(
      int               firstc,
!     long      count,          // only used for incremental search
!     int               indent)         // indent for inside conditionals
! {
!     return getcmdline_int(firstc, count, indent, TRUE);
! }
! 
!     static char_u *
! getcmdline_int(
!     int               firstc,
!     long      count UNUSED,   // only used for incremental search
!     int               indent,         // indent for inside conditionals
!     int               init_ccline)    // clear ccline first
  {
      int               c;
      int               i;
***************
*** 832,845 ****
  #endif
      expand_T  xpc;
      long      *b_im_ptr = NULL;
- #if defined(FEAT_WILDMENU) || defined(FEAT_EVAL)
-     /* Everything that may work recursively should save and restore the
-      * current command line in save_ccline.  That includes update_screen(), a
-      * custom status line may invoke ":normal". */
      struct cmdline_info save_ccline;
! #endif
      int               cmdline_type;
  
  #ifdef FEAT_EVAL
      if (firstc == -1)
      {
--- 839,858 ----
  #endif
      expand_T  xpc;
      long      *b_im_ptr = NULL;
      struct cmdline_info save_ccline;
!     int               did_save_ccline = FALSE;
      int               cmdline_type;
  
+     if (ccline.cmdbuff != NULL)
+     {
+       // Being called recursively.  Since ccline is global, we need to save
+       // the current buffer and restore it when returning.
+       save_cmdline(&save_ccline);
+       did_save_ccline = TRUE;
+     }
+     if (init_ccline)
+       vim_memset(&ccline, 0, sizeof(struct cmdline_info));
+ 
  #ifdef FEAT_EVAL
      if (firstc == -1)
      {
***************
*** 868,874 ****
      /* alloc initial ccline.cmdbuff */
      alloc_cmdbuff(exmode_active ? 250 : indent + 1);
      if (ccline.cmdbuff == NULL)
!       return NULL;                        /* out of memory */
      ccline.cmdlen = ccline.cmdpos = 0;
      ccline.cmdbuff[0] = NUL;
      sb_text_start_cmdline();
--- 881,887 ----
      /* alloc initial ccline.cmdbuff */
      alloc_cmdbuff(exmode_active ? 250 : indent + 1);
      if (ccline.cmdbuff == NULL)
!       goto theend;    // out of memory
      ccline.cmdlen = ccline.cmdpos = 0;
      ccline.cmdbuff[0] = NUL;
      sb_text_start_cmdline();
***************
*** 1125,1133 ****
                    p_ls = save_p_ls;
                    p_wmh = save_p_wmh;
                    last_status(FALSE);
-                   save_cmdline(&save_ccline);
                    update_screen(VALID);       /* redraw the screen NOW */
-                   restore_cmdline(&save_ccline);
                    redrawcmd();
                    save_p_ls = -1;
                }
--- 1138,1144 ----
***************
*** 1333,1351 ****
                else
                    new_cmdpos = ccline.cmdpos;
  
-               save_cmdline(&save_ccline);
                c = get_expr_register();
-               restore_cmdline(&save_ccline);
                if (c == '=')
                {
                    /* Need to save and restore ccline.  And set "textlock"
                     * to avoid nasty things like going to another buffer when
                     * evaluating an expression. */
-                   save_cmdline(&save_ccline);
                    ++textlock;
                    p = get_expr_line();
                    --textlock;
-                   restore_cmdline(&save_ccline);
  
                    if (p != NULL)
                    {
--- 1344,1358 ----
***************
*** 1812,1822 ****
                        c = ESC;
                    }
                    else
-                   {
-                       save_cmdline(&save_ccline);
                        c = get_expr_register();
-                       restore_cmdline(&save_ccline);
-                   }
                }
  #endif
                if (c != ESC)       /* use ESC to cancel inserting register */
--- 1819,1825 ----
***************
*** 2187,2193 ****
                    int         len;
                    int         old_firstc;
  
!                   vim_free(ccline.cmdbuff);
                    xpc.xp_context = EXPAND_NOTHING;
                    if (hiscnt == hislen)
                        p = lookfor;    /* back to the old one */
--- 2190,2196 ----
                    int         len;
                    int         old_firstc;
  
!                   VIM_CLEAR(ccline.cmdbuff);
                    xpc.xp_context = EXPAND_NOTHING;
                    if (hiscnt == hislen)
                        p = lookfor;    /* back to the old one */
***************
*** 2486,2496 ****
  #endif
      sb_text_end_cmdline();
  
      {
        char_u *p = ccline.cmdbuff;
  
!       /* Make ccline empty, getcmdline() may try to use it. */
!       ccline.cmdbuff = NULL;
        return p;
      }
  }
--- 2489,2502 ----
  #endif
      sb_text_end_cmdline();
  
+ theend:
      {
        char_u *p = ccline.cmdbuff;
  
!       if (did_save_ccline)
!           restore_cmdline(&save_ccline);
!       else
!           ccline.cmdbuff = NULL;
        return p;
      }
  }
***************
*** 2512,2521 ****
  {
      char_u            *s;
      struct cmdline_info       save_ccline;
      int                       msg_col_save = msg_col;
      int                       msg_silent_save = msg_silent;
  
!     save_cmdline(&save_ccline);
      ccline.cmdprompt = prompt;
      ccline.cmdattr = attr;
  # ifdef FEAT_EVAL
--- 2518,2535 ----
  {
      char_u            *s;
      struct cmdline_info       save_ccline;
+     int                       did_save_ccline = FALSE;
      int                       msg_col_save = msg_col;
      int                       msg_silent_save = msg_silent;
  
!     if (ccline.cmdbuff != NULL)
!     {
!       // Save the values of the current cmdline and restore them below.
!       save_cmdline(&save_ccline);
!       did_save_ccline = TRUE;
!     }
! 
!     vim_memset(&ccline, 0, sizeof(struct cmdline_info));
      ccline.cmdprompt = prompt;
      ccline.cmdattr = attr;
  # ifdef FEAT_EVAL
***************
*** 2524,2531 ****
      ccline.input_fn = (firstc == '@');
  # endif
      msg_silent = 0;
!     s = getcmdline(firstc, 1L, 0);
!     restore_cmdline(&save_ccline);
      msg_silent = msg_silent_save;
      /* Restore msg_col, the prompt from input() may have changed it.
       * But only if called recursively and the commandline is therefore being
--- 2538,2548 ----
      ccline.input_fn = (firstc == '@');
  # endif
      msg_silent = 0;
!     s = getcmdline_int(firstc, 1L, 0, FALSE);
! 
!     if (did_save_ccline)
!       restore_cmdline(&save_ccline);
! 
      msg_silent = msg_silent_save;
      /* Restore msg_col, the prompt from input() may have changed it.
       * But only if called recursively and the commandline is therefore being
***************
*** 3121,3127 ****
  /*
   * Allocate a new command line buffer.
   * Assigns the new buffer to ccline.cmdbuff and ccline.cmdbufflen.
-  * Returns the new value of ccline.cmdbuff and ccline.cmdbufflen.
   */
      static void
  alloc_cmdbuff(int len)
--- 3138,3143 ----
***************
*** 3542,3550 ****
      }
      *ccp = prev_ccline;
      prev_ccline = ccline;
!     ccline.cmdbuff = NULL;
!     ccline.cmdprompt = NULL;
!     ccline.xpc = NULL;
  }
  
  /*
--- 3558,3564 ----
      }
      *ccp = prev_ccline;
      prev_ccline = ccline;
!     ccline.cmdbuff = NULL;  // signal that ccline is not in use
  }
  
  /*
***************
*** 3557,3593 ****
      prev_ccline = *ccp;
  }
  
- #if defined(FEAT_EVAL) || defined(PROTO)
- /*
-  * Save the command line into allocated memory.  Returns a pointer to be
-  * passed to restore_cmdline_alloc() later.
-  * Returns NULL when failed.
-  */
-     char_u *
- save_cmdline_alloc(void)
- {
-     struct cmdline_info *p;
- 
-     p = (struct cmdline_info *)alloc((unsigned)sizeof(struct cmdline_info));
-     if (p != NULL)
-       save_cmdline(p);
-     return (char_u *)p;
- }
- 
- /*
-  * Restore the command line from the return value of save_cmdline_alloc().
-  */
-     void
- restore_cmdline_alloc(char_u *p)
- {
-     if (p != NULL)
-     {
-       restore_cmdline((struct cmdline_info *)p);
-       vim_free(p);
-     }
- }
- #endif
- 
  /*
   * Paste a yank register into the command line.
   * Used by CTRL-R command in command-line mode.
--- 3571,3576 ----
***************
*** 3606,3612 ****
      char_u            *arg;
      char_u            *p;
      int                       allocated;
-     struct cmdline_info       save_ccline;
  
      /* check for valid regname; also accept special characters for CTRL-R in
       * the command line */
--- 3589,3594 ----
***************
*** 3625,3637 ****
      regname = may_get_selection(regname);
  #endif
  
!     /* Need to save and restore ccline.  And set "textlock" to avoid nasty
!      * things like going to another buffer when evaluating an expression. */
!     save_cmdline(&save_ccline);
      ++textlock;
      i = get_spec_reg(regname, &arg, &allocated, TRUE);
      --textlock;
-     restore_cmdline(&save_ccline);
  
      if (i)
      {
--- 3607,3617 ----
      regname = may_get_selection(regname);
  #endif
  
!     // Need to  set "textlock" to avoid nasty things like going to another
!     // buffer when evaluating an expression.
      ++textlock;
      i = get_spec_reg(regname, &arg, &allocated, TRUE);
      --textlock;
  
      if (i)
      {
***************
*** 5601,5607 ****
      sctx_T    save_current_sctx = current_sctx;
      char_u    *pat = NULL;
      void      *ret;
-     struct cmdline_info           save_ccline;
  
      if (xp->xp_arg == NULL || xp->xp_arg[0] == '\0' || xp->xp_line == NULL)
        return NULL;
--- 5581,5586 ----
***************
*** 5624,5638 ****
      args[2].vval.v_number = xp->xp_col;
      args[3].v_type = VAR_UNKNOWN;
  
-     /* Save the cmdline, we don't know what the function may do. */
-     save_ccline = ccline;
-     ccline.cmdbuff = NULL;
-     ccline.cmdprompt = NULL;
      current_sctx = xp->xp_script_ctx;
  
      ret = user_expand_func(xp->xp_arg, 3, args);
  
-     ccline = save_ccline;
      current_sctx = save_current_sctx;
      if (ccline.cmdbuff != NULL)
        ccline.cmdbuff[ccline.cmdlen] = keep;
--- 5603,5612 ----
***************
*** 6481,6487 ****
  
  #if defined(FEAT_EVAL) || defined(FEAT_CMDWIN) || defined(PROTO)
  /*
!  * Get pointer to the command line info to use. cmdline_paste() may clear
   * ccline and put the previous value in prev_ccline.
   */
      static struct cmdline_info *
--- 6455,6461 ----
  
  #if defined(FEAT_EVAL) || defined(FEAT_CMDWIN) || defined(PROTO)
  /*
!  * Get pointer to the command line info to use. save_ccline() may clear
   * ccline and put the previous value in prev_ccline.
   */
      static struct cmdline_info *
***************
*** 7072,7077 ****
--- 7046,7057 ----
      }
  }
  
+     void
+ cmdline_init(void)
+ {
+     vim_memset(&ccline, 0, sizeof(struct cmdline_info));
+ }
+ 
  /*
   * Write history to viminfo file in "fp".
   * When "merge" is TRUE merge history lines with a previously read viminfo
***************
*** 7238,7244 ****
      static int
  open_cmdwin(void)
  {
-     struct cmdline_info       save_ccline;
      bufref_T          old_curbuf;
      win_T             *old_curwin = curwin;
      bufref_T          bufref;
--- 7218,7223 ----
***************
*** 7355,7363 ****
      invalidate_botline();
      redraw_later(SOME_VALID);
  
-     /* Save the command line info, can be used recursively. */
-     save_cmdline(&save_ccline);
- 
      /* No Ex mode here! */
      exmode_active = 0;
  
--- 7334,7339 ----
***************
*** 7394,7403 ****
      KeyTyped = save_KeyTyped;
  # endif
  
-     /* Restore the command line info. */
-     restore_cmdline(&save_ccline);
      cmdwin_type = 0;
- 
      exmode_active = save_exmode;
  
      /* Safety check: The old window or buffer was deleted: It's a bug when
--- 7370,7376 ----
*** ../vim-8.1.0438/src/proto/ex_getln.pro      2018-05-17 13:52:35.000000000 
+0200
--- src/proto/ex_getln.pro      2018-09-30 15:11:35.810356311 +0200
***************
*** 15,22 ****
  void putcmdline(int c, int shift);
  void unputcmdline(void);
  int put_on_cmdline(char_u *str, int len, int redraw);
- char_u *save_cmdline_alloc(void);
- void restore_cmdline_alloc(char_u *p);
  void cmdline_paste_str(char_u *s, int literally);
  void redrawcmdline(void);
  void redrawcmdline_ex(int do_compute_cmdrow);
--- 15,20 ----
***************
*** 54,59 ****
--- 52,58 ----
  int read_viminfo_history(vir_T *virp, int writing);
  void handle_viminfo_history(garray_T *values, int writing);
  void finish_viminfo_history(vir_T *virp);
+ void cmdline_init(void);
  void write_viminfo_history(FILE *fp, int merge);
  void cmd_pchar(int c, int offset);
  int cmd_gchar(int offset);
*** ../vim-8.1.0438/src/getchar.c       2018-09-10 21:04:09.868392665 +0200
--- src/getchar.c       2018-09-30 14:32:29.424816910 +0200
***************
*** 4666,4672 ****
      char_u    *res;
      char_u    *p;
      char_u    *expr;
-     char_u    *save_cmd;
      pos_T     save_cursor;
      int               save_msg_col;
      int               save_msg_row;
--- 4666,4671 ----
***************
*** 4678,4690 ****
        return NULL;
      vim_unescape_csi(expr);
  
-     save_cmd = save_cmdline_alloc();
-     if (save_cmd == NULL)
-     {
-       vim_free(expr);
-       return NULL;
-     }
- 
      /* Forbid changing text or using ":normal" to avoid most of the bad side
       * effects.  Also restore the cursor position. */
      ++textlock;
--- 4677,4682 ----
***************
*** 4700,4706 ****
      msg_col = save_msg_col;
      msg_row = save_msg_row;
  
-     restore_cmdline_alloc(save_cmd);
      vim_free(expr);
  
      if (p == NULL)
--- 4692,4697 ----
*** ../vim-8.1.0438/src/main.c  2018-09-16 14:10:28.300323360 +0200
--- src/main.c  2018-09-30 15:10:50.358720630 +0200
***************
*** 929,934 ****
--- 929,935 ----
      void
  common_init(mparm_T *paramp)
  {
+     cmdline_init();
  
  #ifdef FEAT_MBYTE
      (void)mb_init();  /* init mb_bytelen_tab[] to ones */
*** ../vim-8.1.0438/src/version.c       2018-09-28 23:09:50.558463030 +0200
--- src/version.c       2018-09-30 17:07:43.183446960 +0200
***************
*** 796,797 ****
--- 796,799 ----
  {   /* Add new patch number below this line */
+ /**/
+     439,
  /**/

-- 
hundred-and-one symptoms of being an internet addict:
124. You begin conversations with, "Who is your internet service provider?"

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\  an exciting new programming language -- http://www.Zimbu.org        ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Raspunde prin e-mail lui