# HG changeset patch # User Bram Moolenaar # Date 1610817304 -3600 # Node ID 03acf9c49f076ff083eff32fbb65384dbc22d262 # Parent df929ddb388b526e6ace71237078244942b30a5c patch 8.2.2364: Vim9: line break in lambda accesses freed memory Commit: https://github.com/vim/vim/commit/f898f7c68dc06def1a5ae02ce82a52a82af37cc4 Author: Bram Moolenaar Date: Sat Jan 16 18:09:52 2021 +0100 patch 8.2.2364: Vim9: line break in lambda accesses freed memory Problem: Vim9: line break in lambda accesses freed memory. Solution: Make a copy of the return type. (closes https://github.com/vim/vim/issues/7664) diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim --- a/src/testdir/test_vim9_func.vim +++ b/src/testdir/test_vim9_func.vim @@ -1811,6 +1811,18 @@ enddef def Test_line_continuation_in_lambda() Line_continuation_in_lambda()->assert_equal(['D', 'C', 'B', 'A']) + + var lines =<< trim END + vim9script + var res = [{n: 1, m: 2, s: 'xxx'}] + ->mapnew((_, v: dict): string => printf('%d:%d:%s', + v.n, + v.m, + substitute(v.s, '.*', 'yyy', '') + )) + assert_equal(['1:2:yyy'], res) + END + CheckScriptSuccess(lines) enddef def Test_list_lambda() diff --git a/src/userfunc.c b/src/userfunc.c --- a/src/userfunc.c +++ b/src/userfunc.c @@ -539,7 +539,8 @@ get_lambda_tv( char_u *start, *end; int *old_eval_lavars = eval_lavars_used; int eval_lavars = FALSE; - char_u *tofree = NULL; + char_u *tofree1 = NULL; + char_u *tofree2 = NULL; int equal_arrow = **arg == '('; int white_error = FALSE; @@ -582,6 +583,13 @@ get_lambda_tv( } *arg = s; + // Skipping over linebreaks may make "ret_type" invalid, make a copy. + if (ret_type != NULL) + { + ret_type = vim_strsave(ret_type); + tofree2 = ret_type; + } + // Set up a flag for checking local variables and arguments. if (evaluate) eval_lavars_used = &eval_lavars; @@ -605,7 +613,7 @@ get_lambda_tv( if (evalarg != NULL) { // avoid that the expression gets freed when another line break follows - tofree = evalarg->eval_tofree; + tofree1 = evalarg->eval_tofree; evalarg->eval_tofree = NULL; } @@ -700,9 +708,10 @@ get_lambda_tv( eval_lavars_used = old_eval_lavars; if (evalarg != NULL && evalarg->eval_tofree == NULL) - evalarg->eval_tofree = tofree; + evalarg->eval_tofree = tofree1; else - vim_free(tofree); + vim_free(tofree1); + vim_free(tofree2); if (types_optional) ga_clear_strings(&argtypes); return OK; @@ -715,9 +724,10 @@ errret: vim_free(fp); vim_free(pt); if (evalarg != NULL && evalarg->eval_tofree == NULL) - evalarg->eval_tofree = tofree; + evalarg->eval_tofree = tofree1; else - vim_free(tofree); + vim_free(tofree1); + vim_free(tofree2); eval_lavars_used = old_eval_lavars; return FAIL; } diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -751,6 +751,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 2364, +/**/ 2363, /**/ 2362,