To: vim_dev@googlegroups.com Subject: Patch 8.1.2280 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.1.2280 Problem: Crash when passing partial to substitute(). Solution: Take extra arguments into account. (closes #5186) Files: src/userfunc.c, src/structs.h, src/regexp.c, src/proto/regexp.pro, src/testdir/test_substitute.vim *** ../vim-8.1.2279/src/userfunc.c 2019-11-06 15:02:46.189199092 +0100 --- src/userfunc.c 2019-11-09 22:20:26.501458325 +0100 *************** *** 1588,1594 **** else if (fp != NULL) { if (funcexe->argv_func != NULL) ! argcount = funcexe->argv_func(argcount, argvars, fp->uf_args.ga_len); if (funcexe->basetv != NULL) --- 1588,1595 ---- else if (fp != NULL) { if (funcexe->argv_func != NULL) ! // postponed filling in the arguments, do it now ! argcount = funcexe->argv_func(argcount, argvars, argv_clear, fp->uf_args.ga_len); if (funcexe->basetv != NULL) *** ../vim-8.1.2279/src/structs.h 2019-11-09 15:32:51.593873994 +0100 --- src/structs.h 2019-11-09 22:08:01.156530546 +0100 *************** *** 1627,1636 **** // // "argv_func", when not NULL, can be used to fill in arguments only when the // invoked function uses them. It is called like this: ! // new_argcount = argv_func(current_argcount, argv, called_func_argcount) // typedef struct { ! int (* argv_func)(int, typval_T *, int); linenr_T firstline; // first line of range linenr_T lastline; // last line of range int *doesrange; // if not NULL: return: function handled range --- 1627,1637 ---- // // "argv_func", when not NULL, can be used to fill in arguments only when the // invoked function uses them. It is called like this: ! // new_argcount = argv_func(current_argcount, argv, partial_argcount, ! // called_func_argcount) // typedef struct { ! int (* argv_func)(int, typval_T *, int, int); linenr_T firstline; // first line of range linenr_T lastline; // last line of range int *doesrange; // if not NULL: return: function handled range *** ../vim-8.1.2279/src/regexp.c 2019-09-07 23:16:16.830370948 +0200 --- src/regexp.c 2019-11-09 22:22:43.840923832 +0100 *************** *** 1784,1808 **** #ifdef FEAT_EVAL /* ! * 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 UNUSED, typval_T *argv, int argcount) { listitem_T *li; int i; char_u *s; ! if (argcount == 0) ! /* called function doesn't take an argument */ ! return 0; ! /* Relies on sl_list to be the first item in staticList10_T. */ ! init_static_list((staticList10_T *)(argv->vval.v_list)); ! /* There are always 10 list items in staticList10_T. */ ! li = argv->vval.v_list->lv_first; for (i = 0; i < 10; ++i) { s = rsm.sm_match->startp[i]; --- 1784,1809 ---- #ifdef FEAT_EVAL /* ! * 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 UNUSED, typval_T *argv, int argskip, int argcount) { listitem_T *li; int i; char_u *s; + 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. ! init_static_list((staticList10_T *)(listarg->vval.v_list)); ! // There are always 10 list items in staticList10_T. ! li = listarg->vval.v_list->lv_first; for (i = 0; i < 10; ++i) { s = rsm.sm_match->startp[i]; *************** *** 1814,1820 **** li->li_tv.vval.v_string = s; li = li->li_next; } ! return 1; } static void --- 1815,1821 ---- li->li_tv.vval.v_string = s; li = li->li_next; } ! return argskip + 1; } static void *** ../vim-8.1.2279/src/proto/regexp.pro 2019-01-20 15:30:36.893328693 +0100 --- src/proto/regexp.pro 2019-11-09 22:02:00.681858742 +0100 *************** *** 1,8 **** /* regexp.c */ int re_multiline(regprog_T *prog); char_u *skip_regexp(char_u *startp, int dirc, int magic, char_u **newp); - int vim_regcomp_had_eol(void); - void free_regexp_stuff(void); reg_extmatch_T *ref_extmatch(reg_extmatch_T *em); void unref_extmatch(reg_extmatch_T *em); char_u *regtilde(char_u *source, int magic); --- 1,6 ---- *************** *** 10,17 **** --- 8,17 ---- int vim_regsub_multi(regmmatch_T *rmp, linenr_T lnum, char_u *source, char_u *dest, int copy, int magic, int backslash); char_u *reg_submatch(int no); list_T *reg_submatch_list(int no); + int vim_regcomp_had_eol(void); regprog_T *vim_regcomp(char_u *expr_arg, int re_flags); void vim_regfree(regprog_T *prog); + void free_regexp_stuff(void); int regprog_in_use(regprog_T *prog); int vim_regexec_prog(regprog_T **prog, int ignore_case, char_u *line, colnr_T col); int vim_regexec(regmatch_T *rmp, char_u *line, colnr_T col); *** ../vim-8.1.2279/src/testdir/test_substitute.vim 2019-10-31 04:38:31.353833447 +0100 --- src/testdir/test_substitute.vim 2019-11-09 22:15:31.102634621 +0100 *************** *** 405,410 **** --- 405,418 ---- 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 + " Tests for *sub-replace-special* and *sub-replace-expression* on :substitute. " Execute a list of :substitute command tests *** ../vim-8.1.2279/src/version.c 2019-11-09 21:28:06.526103024 +0100 --- src/version.c 2019-11-09 22:06:10.960935259 +0100 *************** *** 743,744 **** --- 743,746 ---- { /* Add new patch number below this line */ + /**/ + 2280, /**/ -- Q: What is a patch 22? A: A patch you need to include to make it possible to include patches. /// 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 ///