mirror of
https://github.com/vim/vim.git
synced 2025-07-26 11:04:33 -04:00
patch 8.1.2282: crash when passing many arguments through a partial
Problem: Crash when passing many arguments through a partial. (Andy Massimino) Solution: Check the number of arguments. (closes #5186)
This commit is contained in:
parent
ee85702c10
commit
4c054e9fb2
@ -2527,6 +2527,12 @@ common_function(typval_T *argvars, typval_T *rettv, int is_funcref)
|
|||||||
list = argvars[arg_idx].vval.v_list;
|
list = argvars[arg_idx].vval.v_list;
|
||||||
if (list == NULL || list->lv_len == 0)
|
if (list == NULL || list->lv_len == 0)
|
||||||
arg_idx = 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)
|
if (dict_idx > 0 || arg_idx > 0 || arg_pt != NULL || is_funcref)
|
||||||
|
@ -3,6 +3,7 @@ void func_init(void);
|
|||||||
hashtab_T *func_tbl_get(void);
|
hashtab_T *func_tbl_get(void);
|
||||||
int get_lambda_tv(char_u **arg, typval_T *rettv, int evaluate);
|
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);
|
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);
|
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);
|
ufunc_T *find_func(char_u *name);
|
||||||
void save_funccal(funccal_entry_T *entry);
|
void save_funccal(funccal_entry_T *entry);
|
||||||
|
@ -2015,12 +2015,18 @@ vim_regsub_both(
|
|||||||
call_func(s, -1, &rettv, 1, argv, &funcexe);
|
call_func(s, -1, &rettv, 1, argv, &funcexe);
|
||||||
}
|
}
|
||||||
if (matchList.sl_list.lv_len > 0)
|
if (matchList.sl_list.lv_len > 0)
|
||||||
/* fill_submatch_list() was called */
|
// fill_submatch_list() was called
|
||||||
clear_submatch_list(&matchList);
|
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);
|
eval_result = tv_get_string_buf_chk(&rettv, buf);
|
||||||
if (eval_result != NULL)
|
if (eval_result != NULL)
|
||||||
eval_result = vim_strsave(eval_result);
|
eval_result = vim_strsave(eval_result);
|
||||||
|
}
|
||||||
clear_tv(&rettv);
|
clear_tv(&rettv);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -496,6 +496,8 @@ func Test_funcref()
|
|||||||
let OneByRef = 'One'->funcref()
|
let OneByRef = 'One'->funcref()
|
||||||
call assert_equal(2, OneByRef())
|
call assert_equal(2, OneByRef())
|
||||||
call assert_fails('echo funcref("{")', 'E475:')
|
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
|
endfunc
|
||||||
|
|
||||||
func Test_setmatches()
|
func Test_setmatches()
|
||||||
|
@ -408,9 +408,20 @@ endfunc
|
|||||||
func SubReplacer(text, submatches)
|
func SubReplacer(text, submatches)
|
||||||
return a:text .. a:submatches[0] .. a:text
|
return a:text .. a:submatches[0] .. a:text
|
||||||
endfunc
|
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()
|
func Test_substitute_partial()
|
||||||
call assert_equal('1foo2foo3', substitute('123', '2', function('SubReplacer', ['foo']), 'g'))
|
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
|
endfunc
|
||||||
|
|
||||||
" Tests for *sub-replace-special* and *sub-replace-expression* on :substitute.
|
" Tests for *sub-replace-special* and *sub-replace-expression* on :substitute.
|
||||||
|
@ -408,7 +408,7 @@ deref_func_name(char_u *name, int *lenp, partial_T **partialp, int no_autoload)
|
|||||||
* Give an error message with a function name. Handle <SNR> things.
|
* Give an error message with a function name. Handle <SNR> things.
|
||||||
* "ermsg" is to be passed without translation, use N_() instead of _().
|
* "ermsg" is to be passed without translation, use N_() instead of _().
|
||||||
*/
|
*/
|
||||||
static void
|
void
|
||||||
emsg_funcname(char *ermsg, char_u *name)
|
emsg_funcname(char *ermsg, char_u *name)
|
||||||
{
|
{
|
||||||
char_u *p;
|
char_u *p;
|
||||||
@ -1537,7 +1537,14 @@ call_func(
|
|||||||
if (error == ERROR_NONE && partial->pt_argc > 0)
|
if (error == ERROR_NONE && partial->pt_argc > 0)
|
||||||
{
|
{
|
||||||
for (argv_clear = 0; argv_clear < partial->pt_argc; ++argv_clear)
|
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]);
|
copy_tv(&partial->pt_argv[argv_clear], &argv[argv_clear]);
|
||||||
|
}
|
||||||
for (i = 0; i < argcount_in; ++i)
|
for (i = 0; i < argcount_in; ++i)
|
||||||
argv[i + argv_clear] = argvars_in[i];
|
argv[i + argv_clear] = argvars_in[i];
|
||||||
argvars = argv;
|
argvars = argv;
|
||||||
@ -1672,6 +1679,7 @@ call_func(
|
|||||||
if (error == ERROR_NONE)
|
if (error == ERROR_NONE)
|
||||||
ret = OK;
|
ret = OK;
|
||||||
|
|
||||||
|
theend:
|
||||||
/*
|
/*
|
||||||
* Report an error unless the argument evaluation or function call has been
|
* Report an error unless the argument evaluation or function call has been
|
||||||
* cancelled due to an aborting error, an interrupt, or an exception.
|
* cancelled due to an aborting error, an interrupt, or an exception.
|
||||||
|
@ -741,6 +741,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
2282,
|
||||||
/**/
|
/**/
|
||||||
2281,
|
2281,
|
||||||
/**/
|
/**/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user