Patch 8.2.3756
Problem:    might crash when callback is not valid.
Solution:   Check for valid callback. (Yegappan Lakshmanan, closes #9293)
Files:      src/insexpand.c, src/option.c, src/tag.c, src/job.c,
            src/userfunc.c, src/testdir/test_iminsert.vim,
            src/testdir/test_ins_complete.vim, src/testdir/test_tagfunc.vim


*** ../vim-8.2.3755/src/insexpand.c     2021-12-03 11:08:34.256842709 +0000
--- src/insexpand.c     2021-12-07 12:20:34.468477441 +0000
***************
*** 2329,2342 ****
      if (*curbuf->b_p_tsrfu != NUL)
      {
        // buffer-local option set
-       free_callback(&curbuf->b_tsrfu_cb);
        retval = option_set_callback_func(curbuf->b_p_tsrfu,
                                                        &curbuf->b_tsrfu_cb);
      }
      else
      {
        // global option set
-       free_callback(&tsrfu_cb);
        retval = option_set_callback_func(p_tsrfu, &tsrfu_cb);
      }
  
--- 2329,2340 ----
*** ../vim-8.2.3755/src/option.c        2021-12-06 11:03:50.950900210 +0000
--- src/option.c        2021-12-07 12:10:17.382513874 +0000
***************
*** 7210,7216 ****
        return FAIL;
  
      cb = get_callback(tv);
!     if (cb.cb_name == NULL)
      {
        free_tv(tv);
        return FAIL;
--- 7210,7216 ----
        return FAIL;
  
      cb = get_callback(tv);
!     if (cb.cb_name == NULL || *cb.cb_name == NUL)
      {
        free_tv(tv);
        return FAIL;
*** ../vim-8.2.3755/src/tag.c   2021-12-05 21:46:31.172891155 +0000
--- src/tag.c   2021-12-07 12:21:44.312138332 +0000
***************
*** 1361,1367 ****
      dict_T    *d;
      taggy_T   *tag = &curwin->w_tagstack[curwin->w_tagstackidx];
  
!     if (*curbuf->b_p_tfu == NUL)
        return FAIL;
  
      args[0].v_type = VAR_STRING;
--- 1361,1368 ----
      dict_T    *d;
      taggy_T   *tag = &curwin->w_tagstack[curwin->w_tagstackidx];
  
!     if (*curbuf->b_p_tfu == NUL || curbuf->b_tfu_cb.cb_name == NULL
!                                          || *curbuf->b_tfu_cb.cb_name == NUL)
        return FAIL;
  
      args[0].v_type = VAR_STRING;
*** ../vim-8.2.3755/src/job.c   2021-12-05 22:19:22.832153464 +0000
--- src/job.c   2021-12-07 12:23:45.155602075 +0000
***************
*** 1578,1583 ****
--- 1578,1584 ----
  {
      typval_T  rettv;
      typval_T  argv[1];
+     int               ret;
  
      if (curbuf->b_prompt_interrupt.cb_name == NULL
            || *curbuf->b_prompt_interrupt.cb_name == NUL)
***************
*** 1585,1593 ****
      argv[0].v_type = VAR_UNKNOWN;
  
      got_int = FALSE; // don't skip executing commands
!     call_callback(&curbuf->b_prompt_interrupt, -1, &rettv, 0, argv);
      clear_tv(&rettv);
!     return TRUE;
  }
  
  /*
--- 1586,1594 ----
      argv[0].v_type = VAR_UNKNOWN;
  
      got_int = FALSE; // don't skip executing commands
!     ret = call_callback(&curbuf->b_prompt_interrupt, -1, &rettv, 0, argv);
      clear_tv(&rettv);
!     return ret == FAIL ? FALSE : TRUE;
  }
  
  /*
*** ../vim-8.2.3755/src/userfunc.c      2021-12-06 15:06:49.335517805 +0000
--- src/userfunc.c      2021-12-07 12:19:37.004775284 +0000
***************
*** 3146,3151 ****
--- 3146,3152 ----
  
  /*
   * Invoke call_func() with a callback.
+  * Returns FAIL if the callback could not be called.
   */
      int
  call_callback(
***************
*** 3159,3164 ****
--- 3160,3167 ----
      funcexe_T funcexe;
      int               ret;
  
+     if (callback->cb_name == NULL || *callback->cb_name == NUL)
+       return FAIL;
      CLEAR_FIELD(funcexe);
      funcexe.evaluate = TRUE;
      funcexe.partial = callback->cb_partial;
***************
*** 3170,3176 ****
  
  /*
   * call the 'callback' function and return the result as a number.
!  * Returns -1 when calling the function fails.  Uses argv[0] to argv[argc - 1]
   * for the function arguments. argv[argc] should have type VAR_UNKNOWN.
   */
      varnumber_T
--- 3173,3179 ----
  
  /*
   * call the 'callback' function and return the result as a number.
!  * Returns -2 when calling the function fails.  Uses argv[0] to argv[argc - 1]
   * for the function arguments. argv[argc] should have type VAR_UNKNOWN.
   */
      varnumber_T
***************
*** 3184,3190 ****
      varnumber_T       retval;
  
      if (call_callback(callback, 0, &rettv, argcount, argvars) == FAIL)
!       return -1;
  
      retval = tv_get_number_chk(&rettv, NULL);
      clear_tv(&rettv);
--- 3187,3193 ----
      varnumber_T       retval;
  
      if (call_callback(callback, 0, &rettv, argcount, argvars) == FAIL)
!       return -2;
  
      retval = tv_get_number_chk(&rettv, NULL);
      clear_tv(&rettv);
*** ../vim-8.2.3755/src/testdir/test_iminsert.vim       2021-12-06 
11:03:50.954900203 +0000
--- src/testdir/test_iminsert.vim       2021-12-07 12:10:17.382513874 +0000
***************
*** 257,262 ****
--- 257,275 ----
    set imstatusfunc=()\ =>\ IMstatusfunc1(a)
    call assert_fails('normal! i', 'E117:')
  
+   " set 'imactivatefunc' and 'imstatusfunc' to a non-existing function
+   set imactivatefunc=IMactivatefunc1
+   set imstatusfunc=IMstatusfunc1
+   call assert_fails("set imactivatefunc=function('NonExistingFunc')", 'E700:')
+   call assert_fails("set imstatusfunc=function('NonExistingFunc')", 'E700:')
+   call assert_fails("let &imactivatefunc = function('NonExistingFunc')", 
'E700:')
+   call assert_fails("let &imstatusfunc = function('NonExistingFunc')", 
'E700:')
+   let g:IMactivatefunc_called = 0
+   let g:IMstatusfunc_called = 0
+   normal! i
+   call assert_equal(2, g:IMactivatefunc_called)
+   call assert_equal(2, g:IMstatusfunc_called)
+ 
    " cleanup
    delfunc IMactivatefunc1
    delfunc IMstatusfunc1
*** ../vim-8.2.3755/src/testdir/test_ins_complete.vim   2021-12-06 
11:03:50.954900203 +0000
--- src/testdir/test_ins_complete.vim   2021-12-07 12:10:17.382513874 +0000
***************
*** 1074,1079 ****
--- 1074,1088 ----
    call assert_fails('call feedkeys("A\<C-X>\<C-U>\<Esc>", "x")', 'E117:')
    call assert_equal([], g:MycompleteFunc2_args)
  
+   " set 'completefunc' to a non-existing function
+   set completefunc=MycompleteFunc2
+   call setline(1, 'five')
+   call assert_fails("set completefunc=function('NonExistingFunc')", 'E700:')
+   call assert_fails("let &completefunc = function('NonExistingFunc')", 
'E700:')
+   let g:MycompleteFunc2_args = []
+   call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
+   call assert_equal([[1, ''], [0, 'five']], g:MycompleteFunc2_args)
+ 
    " cleanup
    delfunc MycompleteFunc1
    delfunc MycompleteFunc2
***************
*** 1285,1290 ****
--- 1294,1308 ----
    call assert_fails('call feedkeys("A\<C-X>\<C-O>\<Esc>", "x")', 'E117:')
    call assert_equal([], g:MyomniFunc2_args)
  
+   " set 'omnifunc' to a non-existing function
+   set omnifunc=MyomniFunc2
+   call setline(1, 'nine')
+   call assert_fails("set omnifunc=function('NonExistingFunc')", 'E700:')
+   call assert_fails("let &omnifunc = function('NonExistingFunc')", 'E700:')
+   let g:MyomniFunc2_args = []
+   call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
+   call assert_equal([[1, ''], [0, 'nine']], g:MyomniFunc2_args)
+ 
    " cleanup
    delfunc MyomniFunc1
    delfunc MyomniFunc2
***************
*** 1522,1527 ****
--- 1540,1555 ----
    call feedkeys("A\<C-X>\<C-T>\<Esc>", "x")
    call assert_equal('sunday', getline(1))
    call assert_equal([[1, ''], [0, 'sun']], g:MytsrFunc4_args)
+   %bw!
+ 
+   " set 'thesaurusfunc' to a non-existing function
+   set thesaurusfunc=MytsrFunc2
+   call setline(1, 'ten')
+   call assert_fails("set thesaurusfunc=function('NonExistingFunc')", 'E700:')
+   call assert_fails("let &thesaurusfunc = function('NonExistingFunc')", 
'E700:')
+   let g:MytsrFunc2_args = []
+   call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
+   call assert_equal([[1, ''], [0, 'ten']], g:MytsrFunc2_args)
  
    " cleanup
    set thesaurusfunc&
*** ../vim-8.2.3755/src/testdir/test_tagfunc.vim        2021-12-06 
11:03:50.954900203 +0000
--- src/testdir/test_tagfunc.vim        2021-12-07 12:10:17.382513874 +0000
***************
*** 317,322 ****
--- 317,327 ----
    call assert_fails("tag a17", "E117:")
    call assert_equal([], g:MytagFunc3_args)
  
+   " set 'tagfunc' to a non-existing function
+   call assert_fails("set tagfunc=function('NonExistingFunc')", 'E700:')
+   call assert_fails("let &tagfunc = function('NonExistingFunc')", 'E700:')
+   call assert_fails("tag axb123", 'E426:')
+ 
    " cleanup
    delfunc MytagFunc1
    delfunc MytagFunc2
*** ../vim-8.2.3755/src/version.c       2021-12-07 11:03:35.260224997 +0000
--- src/version.c       2021-12-07 12:12:12.602367161 +0000
***************
*** 755,756 ****
--- 755,758 ----
  {   /* Add new patch number below this line */
+ /**/
+     3756,
  /**/

-- 
All good vision statements are created by groups of people with bloated
bladders who would rather be doing anything else.
                                (Scott Adams - The Dilbert principle)

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///                                                                      \\\
\\\        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
 \\\            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].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/20211207122431.A86F01C0DD5%40moolenaar.net.

Raspunde prin e-mail lui