mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
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:
parent
60a7184185
commit
dbb386e1b2
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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']
|
||||
|
Loading…
Reference in New Issue
Block a user