To: vim_dev@googlegroups.com Subject: Patch 8.2.2001 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.2001 Problem: Vim9: :def function does not apply 'maxfuncdepth'. Solution: Use 'maxfuncdepth'. (issue #7313) Files: src/vim9execute.c, src/userfunc.c, src/proto/userfunc.pro, src/testdir/test_vim9_func.vim *** ../vim-8.2.2000/src/vim9execute.c 2020-11-12 12:08:47.982254065 +0100 --- src/vim9execute.c 2020-11-17 18:17:53.023959207 +0100 *************** *** 227,232 **** --- 227,236 ---- == FAIL) return FAIL; + // If depth of calling is getting too high, don't execute the function. + if (funcdepth_increment() == FAIL) + return FAIL; + // Move the vararg-list to below the missing optional arguments. if (vararg_count > 0 && arg_to_add > 0) *STACK_TV_BOT(arg_to_add - 1) = *STACK_TV_BOT(-1); *************** *** 503,508 **** --- 507,513 ---- ectx->ec_stack.ga_len = top + 1; *STACK_TV_BOT(-1) = *STACK_TV(idx); + funcdepth_decrement(); return OK; } *************** *** 835,840 **** --- 840,846 ---- cmdmod_T save_cmdmod; int restore_cmdmod = FALSE; int trylevel_at_start = trylevel; + int orig_funcdepth; // Get pointer to item in the stack. #define STACK_TV(idx) (((typval_T *)ectx.ec_stack.ga_data) + idx) *************** *** 870,880 **** --- 876,894 ---- } } + // If depth of calling is getting too high, don't execute the function. + orig_funcdepth = funcdepth_get(); + if (funcdepth_increment() == FAIL) + return FAIL; + CLEAR_FIELD(ectx); ectx.ec_dfunc_idx = ufunc->uf_dfunc_idx; ga_init2(&ectx.ec_stack, sizeof(typval_T), 500); if (ga_grow(&ectx.ec_stack, 20) == FAIL) + { + funcdepth_decrement(); return FAIL; + } ga_init2(&ectx.ec_trystack, sizeof(trycmd_T), 10); ga_init2(&ectx.ec_funcrefs, sizeof(partial_T *), 10); *************** *** 2941,2946 **** --- 2955,2961 ---- if (ret != OK && did_emsg == did_emsg_before) semsg(_(e_unknown_error_while_executing_str), printable_func_name(ufunc)); + funcdepth_restore(orig_funcdepth); return ret; } *** ../vim-8.2.2000/src/userfunc.c 2020-11-05 18:45:42.966909992 +0100 --- src/userfunc.c 2020-11-17 18:17:49.439966508 +0100 *************** *** 1373,1378 **** --- 1373,1422 ---- func_clear_free(fp, TRUE); } + static int funcdepth = 0; + + /* + * Increment the function call depth count. + * Return FAIL when going over 'maxfuncdepth'. + * Otherwise return OK, must call funcdepth_decrement() later! + */ + int + funcdepth_increment(void) + { + if (funcdepth >= p_mfd) + { + emsg(_("E132: Function call depth is higher than 'maxfuncdepth'")); + return FAIL; + } + ++funcdepth; + return OK; + } + + void + funcdepth_decrement(void) + { + --funcdepth; + } + + /* + * Get the current function call depth. + */ + int + funcdepth_get(void) + { + return funcdepth; + } + + /* + * Restore the function call depth. This is for cases where there is no + * garantee funcdepth_decrement() can be called exactly the same number of + * times as funcdepth_increment(). + */ + void + funcdepth_restore(int depth) + { + funcdepth = depth; + } /* * Call a user function. *************** *** 1391,1397 **** funccall_T *fc; int save_did_emsg; int default_arg_err = FALSE; - static int depth = 0; dictitem_T *v; int fixvar_idx = 0; // index in fixvar[] int i; --- 1435,1440 ---- *************** *** 1406,1420 **** #endif ESTACK_CHECK_DECLARATION ! // If depth of calling is getting too high, don't execute the function ! if (depth >= p_mfd) { - emsg(_("E132: Function call depth is higher than 'maxfuncdepth'")); rettv->v_type = VAR_NUMBER; rettv->vval.v_number = -1; return; } - ++depth; line_breakcheck(); // check for CTRL-C hit --- 1449,1461 ---- #endif ESTACK_CHECK_DECLARATION ! // If depth of calling is getting too high, don't execute the function. ! if (funcdepth_increment() == FAIL) { rettv->v_type = VAR_NUMBER; rettv->vval.v_number = -1; return; } line_breakcheck(); // check for CTRL-C hit *************** *** 1437,1443 **** { // Execute the function, possibly compiling it first. call_def_function(fp, argcount, argvars, funcexe->partial, rettv); ! --depth; current_funccal = fc->caller; free_funccal(fc); return; --- 1478,1484 ---- { // Execute the function, possibly compiling it first. call_def_function(fp, argcount, argvars, funcexe->partial, rettv); ! funcdepth_decrement(); current_funccal = fc->caller; free_funccal(fc); return; *************** *** 1783,1790 **** } did_emsg |= save_did_emsg; ! --depth; ! cleanup_function_call(fc); } --- 1824,1830 ---- } did_emsg |= save_did_emsg; ! funcdepth_decrement(); cleanup_function_call(fc); } *** ../vim-8.2.2000/src/proto/userfunc.pro 2020-11-05 18:45:42.966909992 +0100 --- src/proto/userfunc.pro 2020-11-17 18:17:45.811973886 +0100 *************** *** 14,19 **** --- 14,23 ---- int func_is_global(ufunc_T *ufunc); int func_name_refcount(char_u *name); void copy_func(char_u *lambda, char_u *global); + int funcdepth_increment(void); + void funcdepth_decrement(void); + int funcdepth_get(void); + void funcdepth_restore(int depth); int call_user_func_check(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rettv, funcexe_T *funcexe, dict_T *selfdict); void save_funccal(funccal_entry_T *entry); void restore_funccal(void); *** ../vim-8.2.2000/src/testdir/test_vim9_func.vim 2020-11-05 18:45:42.970909982 +0100 --- src/testdir/test_vim9_func.vim 2020-11-17 18:21:31.963501714 +0100 *************** *** 49,54 **** --- 49,84 ---- call delete('XTest_compile_error') enddef + def CallRecursive(n: number): number + return CallRecursive(n + 1) + enddef + + def CallMapRecursive(l: list): number + return map(l, {_, v -> CallMapRecursive([v])})[0] + enddef + + def Test_funcdepth_error() + set maxfuncdepth=10 + + var caught = false + try + CallRecursive(1) + catch /E132:/ + caught = true + endtry + assert_true(caught) + + caught = false + try + CallMapRecursive([1]) + catch /E132:/ + caught = true + endtry + assert_true(caught) + + set maxfuncdepth& + enddef + def ReturnString(): string return 'string' enddef *** ../vim-8.2.2000/src/version.c 2020-11-16 22:11:39.625599176 +0100 --- src/version.c 2020-11-17 18:22:21.927394611 +0100 *************** *** 752,753 **** --- 752,755 ---- { /* Add new patch number below this line */ + /**/ + 2001, /**/ -- hundred-and-one symptoms of being an internet addict: 264. You turn to the teletext page "surfing report" and are surprised that it is about sizes of waves and a weather forecast for seaside resorts. /// 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 ///