vim-patch:8.1.2280: crash when passing partial to substitute()

Problem:    Crash when passing partial to substitute().
Solution:   Take extra arguments into account. (closes vim/vim#5186)
b0745b221d
This commit is contained in:
Jan Edmund Lazo 2020-03-18 00:47:46 -04:00
parent 60a7184185
commit dbb386e1b2
No known key found for this signature in database
GPG Key ID: 64915E6E9F735B15
4 changed files with 25 additions and 11 deletions

View File

@ -6382,7 +6382,9 @@ call_func(
error = ERROR_DELETED;
} else if (fp != NULL) {
if (argv_func != NULL) {
argcount = argv_func(argcount, argvars, fp->uf_args.ga_len);
// postponed filling in the arguments, do it now
argcount = argv_func(argcount, argvars, argv_clear,
fp->uf_args.ga_len);
}
if (fp->uf_flags & FC_RANGE) {
*doesrange = true;

View File

@ -187,7 +187,7 @@ extern const list_T *eval_msgpack_type_lists[LAST_MSGPACK_TYPE + 1];
#undef LAST_MSGPACK_TYPE
typedef int (*ArgvFunc)(int current_argcount, typval_T *argv,
typedef int (*ArgvFunc)(int current_argcount, typval_T *argv, int argskip,
int called_func_argcount);
/// trans_function_name() flags

View File

@ -6491,20 +6491,24 @@ typedef struct {
static regsubmatch_T rsm; // can only be used when can_f_submatch is true
/// Put the submatches in "argv[0]" which is a list passed into call_func() by
/// vim_regsub_both().
static int fill_submatch_list(int argc, typval_T *argv, int argcount)
/// Put the submatches in "argv[argskip]" which is a list passed into
/// call_func() by vim_regsub_both().
static int fill_submatch_list(int argc FUNC_ATTR_UNUSED, typval_T *argv,
int argskip, int argcount)
FUNC_ATTR_NONNULL_ALL
{
if (argcount == 0) {
// called function doesn't take an argument
return 0;
typval_T *listarg = argv + argskip;
if (argcount == argskip) {
// called function doesn't take a submatches argument
return argskip;
}
// Relies on sl_list to be the first item in staticList10_T.
tv_list_init_static10((staticList10_T *)argv->vval.v_list);
tv_list_init_static10((staticList10_T *)listarg->vval.v_list);
// There are always 10 list items in staticList10_T.
listitem_T *li = tv_list_first(argv->vval.v_list);
listitem_T *li = tv_list_first(listarg->vval.v_list);
for (int i = 0; i < 10; i++) {
char_u *s = rsm.sm_match->startp[i];
if (s == NULL || rsm.sm_match->endp[i] == NULL) {
@ -6516,7 +6520,7 @@ static int fill_submatch_list(int argc, typval_T *argv, int argcount)
TV_LIST_ITEM_TV(li)->vval.v_string = s;
li = TV_LIST_ITEM_NEXT(argv->vval.v_list, li);
}
return 1;
return argskip + 1;
}
static void clear_submatch_list(staticList10_T *sl)

View File

@ -613,6 +613,14 @@ func Test_sub_replace_10()
call assert_equal('1aaa', substitute('123', '1\zs\|[23]', 'a', 'g'))
endfunc
func SubReplacer(text, submatches)
return a:text .. a:submatches[0] .. a:text
endfunc
func Test_substitute_partial()
call assert_equal('1foo2foo3', substitute('123', '2', function('SubReplacer', ['foo']), 'g'))
endfunc
func Test_sub_cmd_9()
new
let input = ['1 aaa', '2 aaa', '3 aaa']