From 28d71b566a29ceea3a2d05bcee9264ed5d630d42 Mon Sep 17 00:00:00 2001 From: Yegappan Lakshmanan Date: Fri, 12 Jan 2024 17:21:55 +0100 Subject: patch 9.1.0017: [security]: use-after-free in eval1_emsg() Problem: use-after-free in eval1_emsg() when an empty line follows a lambda (by @yu3s) Solution: only set evalarg->eval_using_cmdline = FALSE when the *arg pointer is not null fixes: #13833 closes: #13841 Signed-off-by: Yegappan Lakshmanan Signed-off-by: Christian Brabandt --- src/eval.c | 11 +++++++++-- src/testdir/test_vim9_script.vim | 25 +++++++++++++++++++++++++ src/version.c | 2 ++ 3 files changed, 36 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/eval.c b/src/eval.c index 815d13d42a..bf053dfb69 100644 --- a/src/eval.c +++ b/src/eval.c @@ -2699,6 +2699,9 @@ eval_next_non_blank(char_u *arg, evalarg_T *evalarg, int *getnext) /* * To be called after eval_next_non_blank() sets "getnext" to TRUE. * Only called for Vim9 script. + * + * If "arg" is not NULL, then the caller should assign the return value to + * "arg". */ char_u * eval_next_line(char_u *arg, evalarg_T *evalarg) @@ -2747,8 +2750,12 @@ eval_next_line(char_u *arg, evalarg_T *evalarg) } // Advanced to the next line, "arg" no longer points into the previous - // line. - evalarg->eval_using_cmdline = FALSE; + // line. The caller assigns the return value to "arg". + // If "arg" is NULL, then the return value is discarded. In that case, + // "arg" still points to the previous line. So don't reset + // "eval_using_cmdline". + if (arg != NULL) + evalarg->eval_using_cmdline = FALSE; return skipwhite(line); } diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index 7ae4d553e3..77b8831d45 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -4906,6 +4906,31 @@ def Test_for_stmt_space_before_type() v9.CheckSourceFailure(lines, 'E1059: No white space allowed before colon: :number in range(10)', 2) enddef +" This test used to cause an use-after-free memory access +def Test_for_empty_line_after_lambda() + var lines =<< trim END + vim9script + echomsg range(0, 2)->map((_, v) => { + return 1 + }) + + assert_equal('[1, 1, 1]', v:statusmsg) + END + v9.CheckSourceSuccess(lines) + + lines =<< trim END + vim9script + echomsg range(0, 1)->map((_, v) => { + return 1 + }) range(0, 1)->map((_, v) => { + return 2 + }) # comment + + assert_equal('[1, 1] [2, 2]', v:statusmsg) + END + v9.CheckSourceSuccess(lines) +enddef + " Keep this last, it messes up highlighting. def Test_substitute_cmd() new diff --git a/src/version.c b/src/version.c index 2e178f3bb3..f440140a4b 100644 --- a/src/version.c +++ b/src/version.c @@ -704,6 +704,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 17, /**/ 16, /**/ -- cgit v1.2.3