Skip to content

Commit f898f7c

Browse files
committed
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 #7664)
1 parent 9ebcf23 commit f898f7c

3 files changed

Lines changed: 30 additions & 6 deletions

File tree

src/testdir/test_vim9_func.vim

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1811,6 +1811,18 @@ enddef
18111811

18121812
def Test_line_continuation_in_lambda()
18131813
Line_continuation_in_lambda()->assert_equal(['D', 'C', 'B', 'A'])
1814+
1815+
var lines =<< trim END
1816+
vim9script
1817+
var res = [{n: 1, m: 2, s: 'xxx'}]
1818+
->mapnew((_, v: dict<any>): string => printf('%d:%d:%s',
1819+
v.n,
1820+
v.m,
1821+
substitute(v.s, '.*', 'yyy', '')
1822+
))
1823+
assert_equal(['1:2:yyy'], res)
1824+
END
1825+
CheckScriptSuccess(lines)
18141826
enddef
18151827

18161828
def Test_list_lambda()

src/userfunc.c

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -539,7 +539,8 @@ get_lambda_tv(
539539
char_u *start, *end;
540540
int *old_eval_lavars = eval_lavars_used;
541541
int eval_lavars = FALSE;
542-
char_u *tofree = NULL;
542+
char_u *tofree1 = NULL;
543+
char_u *tofree2 = NULL;
543544
int equal_arrow = **arg == '(';
544545
int white_error = FALSE;
545546

@@ -582,6 +583,13 @@ get_lambda_tv(
582583
}
583584
*arg = s;
584585

586+
// Skipping over linebreaks may make "ret_type" invalid, make a copy.
587+
if (ret_type != NULL)
588+
{
589+
ret_type = vim_strsave(ret_type);
590+
tofree2 = ret_type;
591+
}
592+
585593
// Set up a flag for checking local variables and arguments.
586594
if (evaluate)
587595
eval_lavars_used = &eval_lavars;
@@ -605,7 +613,7 @@ get_lambda_tv(
605613
if (evalarg != NULL)
606614
{
607615
// avoid that the expression gets freed when another line break follows
608-
tofree = evalarg->eval_tofree;
616+
tofree1 = evalarg->eval_tofree;
609617
evalarg->eval_tofree = NULL;
610618
}
611619

@@ -700,9 +708,10 @@ get_lambda_tv(
700708

701709
eval_lavars_used = old_eval_lavars;
702710
if (evalarg != NULL && evalarg->eval_tofree == NULL)
703-
evalarg->eval_tofree = tofree;
711+
evalarg->eval_tofree = tofree1;
704712
else
705-
vim_free(tofree);
713+
vim_free(tofree1);
714+
vim_free(tofree2);
706715
if (types_optional)
707716
ga_clear_strings(&argtypes);
708717
return OK;
@@ -715,9 +724,10 @@ get_lambda_tv(
715724
vim_free(fp);
716725
vim_free(pt);
717726
if (evalarg != NULL && evalarg->eval_tofree == NULL)
718-
evalarg->eval_tofree = tofree;
727+
evalarg->eval_tofree = tofree1;
719728
else
720-
vim_free(tofree);
729+
vim_free(tofree1);
730+
vim_free(tofree2);
721731
eval_lavars_used = old_eval_lavars;
722732
return FAIL;
723733
}

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -750,6 +750,8 @@ static char *(features[]) =
750750

751751
static int included_patches[] =
752752
{ /* Add new patch number below this line */
753+
/**/
754+
2364,
753755
/**/
754756
2363,
755757
/**/

0 commit comments

Comments
 (0)