To: vim_dev@googlegroups.com Subject: Patch 9.0.0440 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 9.0.0440 Problem: Crash when using mkdir() with "R" flag in compiled function. Solution: Reserve a variable for deferred function calls. Handle more than one argument. Files: src/vim9expr.c, src/vim9execute.c, src/testdir/test_vim9_func.vim *** ../vim-9.0.0439/src/vim9expr.c 2022-09-04 15:40:31.816188110 +0100 --- src/vim9expr.c 2022-09-11 11:36:39.551216568 +0100 *************** *** 833,842 **** } } ! if (STRCMP(name, "writefile") == 0 && argcount > 2) { ! // May have the "D" flag, reserve a variable for a deferred ! // function call. if (get_defer_var_idx(cctx) == 0) idx = -1; } --- 833,843 ---- } } ! if ((STRCMP(name, "writefile") == 0 && argcount > 2) ! || (STRCMP(name, "mkdir") == 0 && argcount > 1)) { ! // May have the "D" or "R" flag, reserve a variable for a ! // deferred function call. if (get_defer_var_idx(cctx) == 0) idx = -1; } *** ../vim-9.0.0439/src/vim9execute.c 2022-09-09 21:35:17.835126936 +0100 --- src/vim9execute.c 2022-09-11 11:46:29.522297907 +0100 *************** *** 932,942 **** return FAIL; func_tv = STACK_TV_BOT(-argcount - 1); ! // TODO: check type is a funcref list_set_item(l, 0, func_tv); ! for (i = 1; i <= argcount; ++i) ! list_set_item(l, i, STACK_TV_BOT(-argcount + i - 1)); ectx->ec_stack.ga_len -= argcount + 1; return OK; } --- 932,948 ---- return FAIL; func_tv = STACK_TV_BOT(-argcount - 1); ! if (func_tv->v_type != VAR_FUNC && func_tv->v_type != VAR_PARTIAL) ! { ! semsg(_(e_expected_str_but_got_str), ! "function or partial", ! vartype_name(func_tv->v_type)); ! return FAIL; ! } list_set_item(l, 0, func_tv); ! for (i = 0; i < argcount; ++i) ! list_set_item(l, i + 1, STACK_TV_BOT(-argcount + i)); ectx->ec_stack.ga_len -= argcount + 1; return OK; } *************** *** 962,968 **** return FAIL; } ! l = add_defer_item(dfunc->df_defer_var_idx - 1, 1, current_ectx); if (l == NULL) { vim_free(name); --- 968,974 ---- return FAIL; } ! l = add_defer_item(dfunc->df_defer_var_idx - 1, argcount, current_ectx); if (l == NULL) { vim_free(name); *** ../vim-9.0.0439/src/testdir/test_vim9_func.vim 2022-09-09 21:35:17.835126936 +0100 --- src/testdir/test_vim9_func.vim 2022-09-11 11:32:06.759772234 +0100 *************** *** 29,35 **** enddef defcompile END ! writefile(lines, 'XTest_compile_error') var buf = g:RunVimInTerminal('-S XTest_compile_error', {rows: 10, wait_for_ruler: 0}) g:WaitForAssert(() => assert_match('Error detected while compiling command line.*Fails.*Variable not found: nothing', --- 29,35 ---- enddef defcompile END ! writefile(lines, 'XTest_compile_error', 'D') var buf = g:RunVimInTerminal('-S XTest_compile_error', {rows: 10, wait_for_ruler: 0}) g:WaitForAssert(() => assert_match('Error detected while compiling command line.*Fails.*Variable not found: nothing', *************** *** 37,48 **** # clean up g:StopVimInTerminal(buf) - delete('XTest_compile_error') enddef def TestCompilingErrorInTry() var dir = 'Xcompdir/autoload' ! mkdir(dir, 'p') var lines =<< trim END vim9script --- 37,47 ---- # clean up g:StopVimInTerminal(buf) enddef def TestCompilingErrorInTry() var dir = 'Xcompdir/autoload' ! mkdir(dir, 'pR') var lines =<< trim END vim9script *************** *** 62,68 **** endtry END lines[1] = 'set rtp=' .. getcwd() .. '/Xcompdir' ! writefile(lines, 'XTest_compile_error') var buf = g:RunVimInTerminal('-S XTest_compile_error', {rows: 10, wait_for_ruler: 0}) g:WaitForAssert(() => assert_match('Error detected while compiling command line.*function script#OnlyCompiled.*Invalid command: invalid', --- 61,67 ---- endtry END lines[1] = 'set rtp=' .. getcwd() .. '/Xcompdir' ! writefile(lines, 'XTest_compile_error', 'D') var buf = g:RunVimInTerminal('-S XTest_compile_error', {rows: 10, wait_for_ruler: 0}) g:WaitForAssert(() => assert_match('Error detected while compiling command line.*function script#OnlyCompiled.*Invalid command: invalid', *************** *** 70,77 **** # clean up g:StopVimInTerminal(buf) - delete('XTest_compile_error') - delete('Xcompdir', 'rf') enddef def Test_comment_error() --- 69,74 ---- *************** *** 171,177 **** def Test_autoload_name_mismatch() var dir = 'Xnamedir/autoload' ! mkdir(dir, 'p') var lines =<< trim END vim9script --- 168,174 ---- def Test_autoload_name_mismatch() var dir = 'Xnamedir/autoload' ! mkdir(dir, 'pR') var lines =<< trim END vim9script *************** *** 190,201 **** v9.CheckScriptFailure(lines, 'E117:', 1) &rtp = save_rtp - delete('Xnamedir', 'rf') enddef def Test_autoload_names() var dir = 'Xandir/autoload' ! mkdir(dir, 'p') var lines =<< trim END func foobar#function() --- 187,197 ---- v9.CheckScriptFailure(lines, 'E117:', 1) &rtp = save_rtp enddef def Test_autoload_names() var dir = 'Xandir/autoload' ! mkdir(dir, 'pR') var lines =<< trim END func foobar#function() *************** *** 218,229 **** v9.CheckDefAndScriptSuccess(lines) &rtp = save_rtp - delete('Xandir', 'rf') enddef def Test_autoload_error_in_script() var dir = 'Xaedir/autoload' ! mkdir(dir, 'p') var lines =<< trim END func scripterror#function() --- 214,224 ---- v9.CheckDefAndScriptSuccess(lines) &rtp = save_rtp enddef def Test_autoload_error_in_script() var dir = 'Xaedir/autoload' ! mkdir(dir, 'pR') var lines =<< trim END func scripterror#function() *************** *** 264,270 **** assert_equal('yes', g:called_function) &rtp = save_rtp - delete('Xaedir', 'rf') enddef def s:CallRecursive(n: number): number --- 259,264 ---- *************** *** 1298,1304 **** enddef defcompile END ! writefile(lines, 'Xscript') didCatch = false try source Xscript --- 1292,1298 ---- enddef defcompile END ! writefile(lines, 'Xscript', 'D') didCatch = false try source Xscript *************** *** 1308,1315 **** didCatch = true endtry assert_true(didCatch) - - delete('Xscript') enddef def Test_call_funcref_wrong_args() --- 1302,1307 ---- *************** *** 2306,2314 **** 'morelines', name) END ! writefile(lines, 'Xcall.vim') source Xcall.vim - delete('Xcall.vim') enddef def Test_vim9script_call_fail_decl() --- 2298,2305 ---- 'morelines', name) END ! writefile(lines, 'Xcall.vim', 'D') source Xcall.vim enddef def Test_vim9script_call_fail_decl() *************** *** 2343,2351 **** enddef defcompile END ! writefile(lines, 'Xcall_const.vim') assert_fails('source Xcall_const.vim', 'E46:', '', 1, 'MyFunc') - delete('Xcall_const.vim') lines =<< trim END const g:Aconst = 77 --- 2334,2341 ---- enddef defcompile END ! writefile(lines, 'Xcall_const.vim', 'D') assert_fails('source Xcall_const.vim', 'E46:', '', 1, 'MyFunc') lines =<< trim END const g:Aconst = 77 *************** *** 2385,2395 **** delfunc g:GoneSoon CallGoneSoon() END ! writefile(lines, 'XToDelFunc') assert_fails('so XToDelFunc', 'E933:', '', 1, 'CallGoneSoon') assert_fails('so XToDelFunc', 'E933:', '', 1, 'CallGoneSoon') - - delete('XToDelFunc') enddef func Test_free_dict_while_in_funcstack() --- 2375,2383 ---- delfunc g:GoneSoon CallGoneSoon() END ! writefile(lines, 'XToDelFunc', 'D') assert_fails('so XToDelFunc', 'E933:', '', 1, 'CallGoneSoon') assert_fails('so XToDelFunc', 'E933:', '', 1, 'CallGoneSoon') enddef func Test_free_dict_while_in_funcstack() *************** *** 2454,2463 **** endfunc Func('text') END ! writefile(lines, 'XVim9Func') so XVim9Func - - delete('XVim9Func') enddef let s:funcResult = 0 --- 2442,2449 ---- endfunc Func('text') END ! writefile(lines, 'XVim9Func', 'D') so XVim9Func enddef let s:funcResult = 0 *************** *** 2700,2706 **** enddef defcompile END ! writefile(lines, 'Xdef') try source Xdef assert_report('should have failed') --- 2686,2692 ---- enddef defcompile END ! writefile(lines, 'Xdef', 'D') try source Xdef assert_report('should have failed') *************** *** 2749,2756 **** v:throwpoint->assert_match('_Func, line 3$') endtry delfunc! g:Func - - delete('Xdef') enddef def Test_deleted_function() --- 2735,2740 ---- *************** *** 3421,3434 **** enddef def Test_closure_in_map() ! mkdir('XclosureDir/tdir', 'p') writefile(['111'], 'XclosureDir/file1') writefile(['222'], 'XclosureDir/file2') writefile(['333'], 'XclosureDir/tdir/file3') TreeWalk('XclosureDir')->assert_equal(['file1', 'file2', {tdir: ['file3']}]) - - delete('XclosureDir', 'rf') enddef def Test_invalid_function_name() --- 3405,3416 ---- enddef def Test_closure_in_map() ! mkdir('XclosureDir/tdir', 'pR') writefile(['111'], 'XclosureDir/file1') writefile(['222'], 'XclosureDir/file2') writefile(['333'], 'XclosureDir/tdir/file3') TreeWalk('XclosureDir')->assert_equal(['file1', 'file2', {tdir: ['file3']}]) enddef def Test_invalid_function_name() *************** *** 3532,3543 **** var it = Iter(l) echo it.__next__() END ! call writefile(lines, 'XpartialCall') try source XpartialCall catch /E1248:/ endtry - call delete('XpartialCall') endfunc def Test_cmd_modifier() --- 3514,3524 ---- var it = Iter(l) echo it.__next__() END ! call writefile(lines, 'XpartialCall', 'D') try source XpartialCall catch /E1248:/ endtry endfunc def Test_cmd_modifier() *************** *** 3631,3639 **** nno call Func() feedkeys("\\e", 'xt') END ! writefile(lines, 'XemsgReset') assert_fails('so XemsgReset', ['E684:', 'E684:'], lines, 2) ! delete('XemsgReset') nunmap au! BufWinLeave enddef --- 3612,3620 ---- nno call Func() feedkeys("\\e", 'xt') END ! writefile(lines, 'XemsgReset', 'D') assert_fails('so XemsgReset', ['E684:', 'E684:'], lines, 2) ! nunmap au! BufWinLeave enddef *************** *** 3698,3704 **** END # can't use CheckScriptFailure, it ignores the :silent! var fname = 'Xdefsilent' ! writefile(lines, fname) var caught = 'no' try exe 'source ' .. fname --- 3679,3685 ---- END # can't use CheckScriptFailure, it ignores the :silent! var fname = 'Xdefsilent' ! writefile(lines, fname, 'D') var caught = 'no' try exe 'source ' .. fname *************** *** 3707,3713 **** assert_match('Func, line 4', v:throwpoint) endtry assert_equal('yes', caught) - delete(fname) enddef def Test_cmdmod_silent_nested() --- 3688,3693 ---- *************** *** 3809,3815 **** feedkeys('g@l', 'n') feedkeys('llll') END ! call writefile(lines, 'XTest_opfunc_error') var buf = g:RunVimInTerminal('-S XTest_opfunc_error', {rows: 6, wait_for_ruler: 0}) g:WaitForAssert(() => assert_match('Press ENTER', term_getline(buf, 6))) --- 3789,3795 ---- feedkeys('g@l', 'n') feedkeys('llll') END ! call writefile(lines, 'XTest_opfunc_error', 'D') var buf = g:RunVimInTerminal('-S XTest_opfunc_error', {rows: 6, wait_for_ruler: 0}) g:WaitForAssert(() => assert_match('Press ENTER', term_getline(buf, 6))) *************** *** 3817,3823 **** # clean up g:StopVimInTerminal(buf) - delete('XTest_opfunc_error') enddef " this was crashing on exit --- 3797,3802 ---- *************** *** 3890,3903 **** function s:close_cb(...) endfunction END ! lines->writefile('Xlegacy.vim') source Xlegacy.vim g:LegacyJob() g:LegacyJob() g:LegacyJob() delfunc g:LegacyJob - delete('Xlegacy.vim') enddef def Test_check_func_arg_types() --- 3869,3881 ---- function s:close_cb(...) endfunction END ! lines->writefile('Xlegacy.vim', 'D') source Xlegacy.vim g:LegacyJob() g:LegacyJob() g:LegacyJob() delfunc g:LegacyJob enddef def Test_check_func_arg_types() *** ../vim-9.0.0439/src/version.c 2022-09-10 22:31:45.962395605 +0100 --- src/version.c 2022-09-11 11:37:42.791084346 +0100 *************** *** 705,706 **** --- 705,708 ---- { /* Add new patch number below this line */ + /**/ + 440, /**/ -- Despite the cost of living, have you noticed how it remains so popular? /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// \\\ \\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///