To: vim_dev@googlegroups.com Subject: Patch 8.2.0908 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ 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(®match, 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(®match); 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\") + 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, "\") + + 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 -- Bram@Moolenaar.net -- 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 ///