Mercurial > vim
changeset 23644:03acf9c49f07 v8.2.2364
patch 8.2.2364: Vim9: line break in lambda accesses freed memory
Commit: https://github.com/vim/vim/commit/f898f7c68dc06def1a5ae02ce82a52a82af37cc4
Author: Bram Moolenaar <Bram@vim.org>
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)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sat, 16 Jan 2021 18:15:04 +0100 |
parents | df929ddb388b |
children | 541984a4d2e7 |
files | src/testdir/test_vim9_func.vim src/userfunc.c src/version.c |
diffstat | 3 files changed, 30 insertions(+), 6 deletions(-) [+] |
line wrap: on
line diff
--- 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<any>): 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()
--- 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; }