Patch 8.2.3560
Problem: Using freed memory with lambda.
Solution: Do not free lines early, keep them until the expression is
finished.
Files: src/eval.c, src/proto/eval.pro, src/userfunc.c, src/vim9compile.c,
src/structs.h, src/globals.h, src/testdir/test_vim9_func.vim
*** ../vim-8.2.3559/src/eval.c 2021-09-09 11:11:58.875602021 +0100
--- src/eval.c 2021-10-23 13:17:23.263893881 +0100
***************
*** 143,149 ****
void
fill_evalarg_from_eap(evalarg_T *evalarg, exarg_T *eap, int skip)
{
! CLEAR_FIELD(*evalarg);
evalarg->eval_flags = skip ? 0 : EVAL_EVALUATE;
if (eap != NULL)
{
--- 143,149 ----
void
fill_evalarg_from_eap(evalarg_T *evalarg, exarg_T *eap, int skip)
{
! init_evalarg(evalarg);
evalarg->eval_flags = skip ? 0 : EVAL_EVALUATE;
if (eap != NULL)
{
***************
*** 2137,2144 ****
// Advanced to the next line, "arg" no longer points into the previous
// line.
! VIM_CLEAR(evalarg->eval_tofree_cmdline);
!
return skipwhite(line);
}
--- 2137,2143 ----
// Advanced to the next line, "arg" no longer points into the previous
// line.
! evalarg->eval_using_cmdline = FALSE;
return skipwhite(line);
}
***************
*** 2160,2165 ****
--- 2159,2174 ----
}
/*
+ * Initialize "evalarg" for use.
+ */
+ void
+ init_evalarg(evalarg_T *evalarg)
+ {
+ CLEAR_POINTER(evalarg);
+ ga_init2(&evalarg->eval_tofree_ga, sizeof(char_u *), 20);
+ }
+
+ /*
* After using "evalarg" filled from "eap": free the memory.
*/
void
***************
*** 2183,2189 ****
evalarg->eval_tofree = NULL;
}
! VIM_CLEAR(evalarg->eval_tofree_cmdline);
VIM_CLEAR(evalarg->eval_tofree_lambda);
}
}
--- 2192,2198 ----
evalarg->eval_tofree = NULL;
}
! ga_clear_strings(&evalarg->eval_tofree_ga);
VIM_CLEAR(evalarg->eval_tofree_lambda);
}
}
***************
*** 2298,2304 ****
if (evalarg == NULL)
{
! CLEAR_FIELD(local_evalarg);
evalarg_used = &local_evalarg;
}
orig_flags = evalarg_used->eval_flags;
--- 2307,2313 ----
if (evalarg == NULL)
{
! init_evalarg(&local_evalarg);
evalarg_used = &local_evalarg;
}
orig_flags = evalarg_used->eval_flags;
***************
*** 2455,2461 ****
if (evalarg == NULL)
{
! CLEAR_FIELD(local_evalarg);
evalarg_used = &local_evalarg;
}
orig_flags = evalarg_used->eval_flags;
--- 2464,2470 ----
if (evalarg == NULL)
{
! init_evalarg(&local_evalarg);
evalarg_used = &local_evalarg;
}
orig_flags = evalarg_used->eval_flags;
***************
*** 2581,2587 ****
if (evalarg == NULL)
{
! CLEAR_FIELD(local_evalarg);
evalarg_used = &local_evalarg;
}
orig_flags = evalarg_used->eval_flags;
--- 2590,2596 ----
if (evalarg == NULL)
{
! init_evalarg(&local_evalarg);
evalarg_used = &local_evalarg;
}
orig_flags = evalarg_used->eval_flags;
*** ../vim-8.2.3559/src/proto/eval.pro 2021-08-11 20:49:19.626869328 +0100
--- src/proto/eval.pro 2021-10-23 12:54:35.361834638 +0100
***************
*** 34,39 ****
--- 34,40 ----
void set_context_for_expression(expand_T *xp, char_u *arg, cmdidx_T cmdidx);
int pattern_match(char_u *pat, char_u *text, int ic);
char_u *skipwhite_and_linebreak(char_u *arg, evalarg_T *evalarg);
+ void init_evalarg(evalarg_T *evalarg);
void clear_evalarg(evalarg_T *evalarg, exarg_T *eap);
int eval0(char_u *arg, typval_T *rettv, exarg_T *eap, evalarg_T *evalarg);
int eval1(char_u **arg, typval_T *rettv, evalarg_T *evalarg);
*** ../vim-8.2.3559/src/userfunc.c 2021-10-22 22:17:49.142382407 +0100
--- src/userfunc.c 2021-10-23 13:19:06.697410154 +0100
***************
*** 1177,1188 ****
if (cmdline != NULL)
{
// Something comes after the "}".
*arg = eap.nextcmd;
// "arg" points into cmdline, need to keep the line and free it later.
! vim_free(evalarg->eval_tofree_cmdline);
! evalarg->eval_tofree_cmdline = cmdline;
}
else
*arg = (char_u *)"";
--- 1177,1193 ----
if (cmdline != NULL)
{
+ garray_T *tfgap = &evalarg->eval_tofree_ga;
+
// Something comes after the "}".
*arg = eap.nextcmd;
// "arg" points into cmdline, need to keep the line and free it later.
! if (ga_grow(tfgap, 1) == OK)
! {
! ((char_u **)(tfgap->ga_data))[tfgap->ga_len++] = cmdline;
! evalarg->eval_using_cmdline = TRUE;
! }
}
else
*arg = (char_u *)"";
***************
*** 4867,4873 ****
return;
}
! CLEAR_FIELD(evalarg);
evalarg.eval_flags = eap->skip ? 0 : EVAL_EVALUATE;
if (eap->skip)
--- 4872,4878 ----
return;
}
! init_evalarg(&evalarg);
evalarg.eval_flags = eap->skip ? 0 : EVAL_EVALUATE;
if (eap->skip)
*** ../vim-8.2.3559/src/vim9compile.c 2021-10-13 15:28:22.759581625 +0100
--- src/vim9compile.c 2021-10-23 13:19:42.153928462 +0100
***************
*** 3702,3708 ****
ufunc_T *ufunc;
evalarg_T evalarg;
! CLEAR_FIELD(evalarg);
evalarg.eval_flags = EVAL_EVALUATE;
evalarg.eval_cctx = cctx;
--- 3702,3708 ----
ufunc_T *ufunc;
evalarg_T evalarg;
! init_evalarg(&evalarg);
evalarg.eval_flags = EVAL_EVALUATE;
evalarg.eval_cctx = cctx;
***************
*** 3733,3743 ****
compile_def_function(ufunc, FALSE, CT_NONE, cctx);
#endif
! // evalarg.eval_tofree_cmdline may have a copy of the last line and "*arg"
! // points into it. Point to the original line to avoid a dangling
pointer.
! if (evalarg.eval_tofree_cmdline != NULL)
{
! size_t off = *arg - evalarg.eval_tofree_cmdline;
*arg = ((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)[cctx->ctx_lnum]
+ off;
--- 3733,3745 ----
compile_def_function(ufunc, FALSE, CT_NONE, cctx);
#endif
! // The last entry in evalarg.eval_tofree_ga is a copy of the last line and
! // "*arg" may point into it. Point into the original line to avoid a
! // dangling pointer.
! if (evalarg.eval_using_cmdline)
{
! garray_T *gap = &evalarg.eval_tofree_ga;
! size_t off = *arg - ((char_u **)gap->ga_data)[gap->ga_len - 1];
*arg = ((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)[cctx->ctx_lnum]
+ off;
***************
*** 4201,4209 ****
{
evalarg_T evalarg;
! CLEAR_FIELD(evalarg);
evalarg.eval_cctx = cctx;
skip_expr(arg, &evalarg);
}
/*
--- 4203,4212 ----
{
evalarg_T evalarg;
! init_evalarg(&evalarg);
evalarg.eval_cctx = cctx;
skip_expr(arg, &evalarg);
+ clear_evalarg(&evalarg, NULL);
}
/*
*** ../vim-8.2.3559/src/structs.h 2021-10-17 14:13:04.832665843 +0100
--- src/structs.h 2021-10-23 13:20:22.318514796 +0100
***************
*** 1906,1913 ****
// pointer to the last line obtained with getsourceline()
char_u *eval_tofree;
! // pointer to the last line of an inline function
! char_u *eval_tofree_cmdline;
// pointer to the lines concatenated for a lambda.
char_u *eval_tofree_lambda;
--- 1906,1916 ----
// pointer to the last line obtained with getsourceline()
char_u *eval_tofree;
! // array with lines of an inline function
! garray_T eval_tofree_ga;
!
! // set when "arg" points into the last entry of "eval_tofree_ga"
! int eval_using_cmdline;
// pointer to the lines concatenated for a lambda.
char_u *eval_tofree_lambda;
*** ../vim-8.2.3559/src/globals.h 2021-09-17 19:45:26.066836056 +0100
--- src/globals.h 2021-10-23 13:31:16.835131030 +0100
***************
*** 1867,1874 ****
// Passed to an eval() function to enable evaluation.
EXTERN evalarg_T EVALARG_EVALUATE
# ifdef DO_INIT
! = {EVAL_EVALUATE, 0, NULL, NULL, NULL, NULL, {0, 0, 0, 0, NULL},
! {0, 0, 0, 0, NULL}, NULL, NULL, NULL}
# endif
;
#endif
--- 1867,1874 ----
// Passed to an eval() function to enable evaluation.
EXTERN evalarg_T EVALARG_EVALUATE
# ifdef DO_INIT
! = {EVAL_EVALUATE, 0, NULL, NULL, NULL, NULL, GA_EMPTY, GA_EMPTY, NULL,
! {0, 0, (int)sizeof(char_u *), 20, NULL}, 0, NULL}
# endif
;
#endif
*** ../vim-8.2.3559/src/testdir/test_vim9_func.vim 2021-09-13
17:25:50.456525311 +0100
--- src/testdir/test_vim9_func.vim 2021-10-23 13:25:58.451395993 +0100
***************
*** 1133,1138 ****
--- 1133,1158 ----
CheckScriptSuccess(lines)
enddef
+ def Test_lambda_in_reduce_line_break()
+ # this was using freed memory
+ var lines =<< trim END
+ vim9script
+ const result: dict<number> =
+ ['Bob', 'Sam', 'Cat', 'Bob', 'Cat', 'Cat']
+ ->reduce((acc, val) => {
+ if has_key(acc, val)
+ acc[val] += 1
+ return acc
+ else
+ acc[val] = 1
+ return acc
+ endif
+ }, {})
+ assert_equal({Bob: 2, Sam: 1, Cat: 3}, result)
+ END
+ CheckScriptSuccess(lines)
+ enddef
+
" Default arg and varargs
def MyDefVarargs(one: string, two = 'foo', ...rest: list<string>): string
var res = one .. ',' .. two
*** ../vim-8.2.3559/src/version.c 2021-10-23 12:34:18.413019131 +0100
--- src/version.c 2021-10-23 13:25:36.539078901 +0100
***************
*** 759,760 ****
--- 759,762 ----
{ /* Add new patch number below this line */
+ /**/
+ 3560,
/**/
--
hundred-and-one symptoms of being an internet addict:
231. You sprinkle Carpet Fresh on the rugs and put your vacuum cleaner
in the front doorway permanently so it always looks like you are
actually attempting to do something about that mess that has amassed
since you discovered the Internet.
/// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
--
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
---
You received this message because you are subscribed to the Google Groups
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/vim_dev/20211023123305.BC530C80053%40moolenaar.net.