To: vim_dev@googlegroups.com Subject: Patch 8.1.2282 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.1.2282 Problem: Crash when passing many arguments through a partial. (Andy Massimino) Solution: Check the number of arguments. (closes #5186) Files: src/userfunc.c, src/proto/userfunc.pro, src/evalfunc.c, src/regexp.c, src/testdir/test_expr.vim, src/testdir/test_substitute.vim *** ../vim-8.1.2281/src/userfunc.c 2019-11-09 22:28:08.183680610 +0100 --- src/userfunc.c 2019-11-09 23:43:24.469991349 +0100 *************** *** 408,414 **** * Give an error message with a function name. Handle things. * "ermsg" is to be passed without translation, use N_() instead of _(). */ ! static void emsg_funcname(char *ermsg, char_u *name) { char_u *p; --- 408,414 ---- * Give an error message with a function name. Handle things. * "ermsg" is to be passed without translation, use N_() instead of _(). */ ! void emsg_funcname(char *ermsg, char_u *name) { char_u *p; *************** *** 1537,1543 **** --- 1537,1550 ---- if (error == ERROR_NONE && partial->pt_argc > 0) { for (argv_clear = 0; argv_clear < partial->pt_argc; ++argv_clear) + { + if (argv_clear + argcount_in >= MAX_FUNC_ARGS) + { + error = ERROR_TOOMANY; + goto theend; + } copy_tv(&partial->pt_argv[argv_clear], &argv[argv_clear]); + } for (i = 0; i < argcount_in; ++i) argv[i + argv_clear] = argvars_in[i]; argvars = argv; *************** *** 1672,1677 **** --- 1679,1685 ---- if (error == ERROR_NONE) ret = OK; + theend: /* * Report an error unless the argument evaluation or function call has been * cancelled due to an aborting error, an interrupt, or an exception. *** ../vim-8.1.2281/src/proto/userfunc.pro 2019-09-16 22:55:57.732006874 +0200 --- src/proto/userfunc.pro 2019-11-09 23:43:44.365918274 +0100 *************** *** 3,8 **** --- 3,9 ---- hashtab_T *func_tbl_get(void); int get_lambda_tv(char_u **arg, typval_T *rettv, int evaluate); char_u *deref_func_name(char_u *name, int *lenp, partial_T **partialp, int no_autoload); + void emsg_funcname(char *ermsg, char_u *name); int get_func_tv(char_u *name, int len, typval_T *rettv, char_u **arg, funcexe_T *funcexe); ufunc_T *find_func(char_u *name); void save_funccal(funccal_entry_T *entry); *** ../vim-8.1.2281/src/evalfunc.c 2019-10-18 20:53:30.693741624 +0200 --- src/evalfunc.c 2019-11-09 23:44:42.221705485 +0100 *************** *** 2527,2532 **** --- 2527,2538 ---- list = argvars[arg_idx].vval.v_list; if (list == NULL || list->lv_len == 0) arg_idx = 0; + else if (list->lv_len > MAX_FUNC_ARGS) + { + emsg_funcname((char *)e_toomanyarg, name); + vim_free(name); + goto theend; + } } } if (dict_idx > 0 || arg_idx > 0 || arg_pt != NULL || is_funcref) *** ../vim-8.1.2281/src/regexp.c 2019-11-09 22:28:08.183680610 +0100 --- src/regexp.c 2019-11-10 00:09:03.563998842 +0100 *************** *** 2015,2026 **** call_func(s, -1, &rettv, 1, argv, &funcexe); } if (matchList.sl_list.lv_len > 0) ! /* fill_submatch_list() was called */ clear_submatch_list(&matchList); ! eval_result = tv_get_string_buf_chk(&rettv, buf); ! if (eval_result != NULL) ! eval_result = vim_strsave(eval_result); clear_tv(&rettv); } else --- 2015,2032 ---- call_func(s, -1, &rettv, 1, argv, &funcexe); } if (matchList.sl_list.lv_len > 0) ! // fill_submatch_list() was called clear_submatch_list(&matchList); ! if (rettv.v_type == VAR_UNKNOWN) ! // something failed, no need to report another error ! eval_result = NULL; ! else ! { ! eval_result = tv_get_string_buf_chk(&rettv, buf); ! if (eval_result != NULL) ! eval_result = vim_strsave(eval_result); ! } clear_tv(&rettv); } else *** ../vim-8.1.2281/src/testdir/test_expr.vim 2019-09-27 13:32:03.064515090 +0200 --- src/testdir/test_expr.vim 2019-11-09 23:50:09.512496782 +0100 *************** *** 496,501 **** --- 496,503 ---- let OneByRef = 'One'->funcref() call assert_equal(2, OneByRef()) call assert_fails('echo funcref("{")', 'E475:') + let OneByRef = funcref("One", repeat(["foo"], 20)) + call assert_fails('let OneByRef = funcref("One", repeat(["foo"], 21))', 'E118:') endfunc func Test_setmatches() *** ../vim-8.1.2281/src/testdir/test_substitute.vim 2019-11-09 22:28:08.183680610 +0100 --- src/testdir/test_substitute.vim 2019-11-10 00:10:11.023740139 +0100 *************** *** 408,416 **** --- 408,427 ---- func SubReplacer(text, submatches) return a:text .. a:submatches[0] .. a:text endfunc + func SubReplacer20(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16, t17, t18, t19, submatches) + return a:t3 .. a:submatches[0] .. a:t11 + endfunc func Test_substitute_partial() call assert_equal('1foo2foo3', substitute('123', '2', function('SubReplacer', ['foo']), 'g')) + + " 19 arguments plus one is just OK + let Replacer = function('SubReplacer20', repeat(['foo'], 19)) + call assert_equal('1foo2foo3', substitute('123', '2', Replacer, 'g')) + + " 20 arguments plus one is too many + let Replacer = function('SubReplacer20', repeat(['foo'], 20)) + call assert_fails("call substitute('123', '2', Replacer, 'g')", 'E118') endfunc " Tests for *sub-replace-special* and *sub-replace-expression* on :substitute. *** ../vim-8.1.2281/src/version.c 2019-11-09 23:26:36.905570965 +0100 --- src/version.c 2019-11-09 23:59:33.674213154 +0100 *************** *** 743,744 **** --- 743,746 ---- { /* Add new patch number below this line */ + /**/ + 2282, /**/ -- hundred-and-one symptoms of being an internet addict: 54. You start tilting your head sideways to smile. :-) /// 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 ///