Patch 8.2.0908
Problem:    Crash when changing the function table while listing it.
Solution:   Bail out when the function table changes. (closes #6209)
Files:      src/userfunc.c, src/testdir/test_timers.vim


*** ../vim-8.2.0907/src/userfunc.c      2020-05-26 11:37:22.198558963 +0200
--- src/userfunc.c      2020-06-05 20:59:54.868839638 +0200
***************
*** 2373,2378 ****
--- 2373,2416 ----
  }
  
  /*
+  * List functions.  When "regmatch" is NULL all of then.
+  * Otherwise functions matching "regmatch".
+  */
+     static void
+ list_functions(regmatch_T *regmatch)
+ {
+     long_u    used = func_hashtab.ht_used;
+     long_u    todo = used;
+     hashitem_T        *ht_array = func_hashtab.ht_array;
+     hashitem_T        *hi;
+ 
+     for (hi = ht_array; todo > 0 && !got_int; ++hi)
+     {
+       if (!HASHITEM_EMPTY(hi))
+       {
+           ufunc_T     *fp = HI2UF(hi);
+ 
+           --todo;
+           if ((fp->uf_flags & FC_DEAD) == 0
+                   && (regmatch == NULL
+                       ? !message_filtered(fp->uf_name)
+                           && !func_name_refcount(fp->uf_name)
+                       : !isdigit(*fp->uf_name)
+                           && vim_regexec(regmatch, fp->uf_name, 0)))
+           {
+               list_func_head(fp, FALSE);
+               if (used != func_hashtab.ht_used
+                       || ht_array != func_hashtab.ht_array)
+               {
+                   emsg(_("E454: function list was modified"));
+                   return;
+               }
+           }
+       }
+     }
+ }
+ 
+ /*
   * ":function" also supporting nested ":def".
   * Returns a pointer to the function or NULL if no function defined.
   */
***************
*** 2407,2413 ****
      funcdict_T        fudi;
      static int        func_nr = 0;        // number for nameless function
      int               paren;
-     int               todo;
      hashitem_T        *hi;
      int               do_concat = TRUE;
      linenr_T  sourcing_lnum_off;
--- 2445,2450 ----
***************
*** 2428,2449 ****
      if (ends_excmd2(eap->cmd, eap->arg))
      {
        if (!eap->skip)
!       {
!           todo = (int)func_hashtab.ht_used;
!           for (hi = func_hashtab.ht_array; todo > 0 && !got_int; ++hi)
!           {
!               if (!HASHITEM_EMPTY(hi))
!               {
!                   --todo;
!                   fp = HI2UF(hi);
!                   if ((fp->uf_flags & FC_DEAD)
!                                             || message_filtered(fp->uf_name))
!                       continue;
!                   if (!func_name_refcount(fp->uf_name))
!                       list_func_head(fp, FALSE);
!               }
!           }
!       }
        eap->nextcmd = check_nextcmd(eap->arg);
        return NULL;
      }
--- 2465,2471 ----
      if (ends_excmd2(eap->cmd, eap->arg))
      {
        if (!eap->skip)
!           list_functions(NULL);
        eap->nextcmd = check_nextcmd(eap->arg);
        return NULL;
      }
***************
*** 2465,2484 ****
            if (regmatch.regprog != NULL)
            {
                regmatch.rm_ic = p_ic;
! 
!               todo = (int)func_hashtab.ht_used;
!               for (hi = func_hashtab.ht_array; todo > 0 && !got_int; ++hi)
!               {
!                   if (!HASHITEM_EMPTY(hi))
!                   {
!                       --todo;
!                       fp = HI2UF(hi);
!                       if ((fp->uf_flags & FC_DEAD) == 0
!                               && !isdigit(*fp->uf_name)
!                               && vim_regexec(&regmatch, fp->uf_name, 0))
!                           list_func_head(fp, FALSE);
!                   }
!               }
                vim_regfree(regmatch.regprog);
            }
        }
--- 2487,2493 ----
            if (regmatch.regprog != NULL)
            {
                regmatch.rm_ic = p_ic;
!               list_functions(&regmatch);
                vim_regfree(regmatch.regprog);
            }
        }
*** ../vim-8.2.0907/src/testdir/test_timers.vim 2020-05-31 21:27:58.335221898 
+0200
--- src/testdir/test_timers.vim 2020-06-05 20:54:51.601876472 +0200
***************
*** 3,8 ****
--- 3,9 ----
  source check.vim
  CheckFeature timers
  
+ source screendump.vim
  source shared.vim
  source term_util.vim
  
***************
*** 424,427 ****
--- 425,452 ----
    call assert_fails('call timer_start(0, "0")', 'E921')
  endfunc
  
+ func Test_timer_changing_function_list()
+   CheckRunVimInTerminal
+ 
+   " Create a large number of functions.  Should get the "more" prompt.
+   " The typing "G" triggers the timer, which changes the function table.
+   let lines =<< trim END
+     for func in map(range(1,99), "'Func' .. v:val")
+       exe "func " .. func .. "()"
+       endfunc
+     endfor
+     au CmdlineLeave : call timer_start(0, {-> 0})
+   END
+   call writefile(lines, 'XTest_timerchange')
+   let buf = RunVimInTerminal('-S XTest_timerchange', #{rows: 10})
+   call term_sendkeys(buf, ":fu\<CR>")
+   call WaitForAssert({-> assert_match('-- More --', term_getline(buf, 10))})
+   call term_sendkeys(buf, "G")
+   call WaitForAssert({-> assert_match('E454', term_getline(buf, 9))})
+   call term_sendkeys(buf, "\<Esc>")
+ 
+   call StopVimInTerminal(buf)
+   call delete('XTest_timerchange')
+ endfunc
+ 
  " vim: shiftwidth=2 sts=2 expandtab
*** ../vim-8.2.0907/src/version.c       2020-06-05 20:03:07.461321471 +0200
--- src/version.c       2020-06-05 20:56:04.705623245 +0200
***************
*** 748,749 ****
--- 748,751 ----
  {   /* Add new patch number below this line */
+ /**/
+     908,
  /**/

-- 
The software said it requires Windows 95 or better, so I installed Linux.

 /// 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].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/202006051907.055J7BYu1076911%40masaka.moolenaar.net.

Raspunde prin e-mail lui