patch 9.2.0448: Vim9: dangling cmdline pointer after skip_expr_cctx()

Commit: 
https://github.com/vim/vim/commit/4bcc8ba93d4d7b6b216dc6a0365e21676b70c715
Author: Yasuhiro Matsumoto <[email protected]>
Date:   Wed May 6 18:02:09 2026 +0000

    patch 9.2.0448: Vim9: dangling cmdline pointer after skip_expr_cctx()
    
    Problem:  Vim9: dangling cmdline pointer after skip_expr_cctx()
              (Foxe Chen)
    Solution: Extract the cmdline restoration logic from compile_lambda into
              a helper restore_cmdline_arg() and call it from
              skip_expr_cctx() too, so a skipped lambda inside an "else"
              branch does not leave "*arg" pointing into freed evalarg
              memory (Yasuhiro Matsumoto).
    
    fixes:  #20147
    closes: #20148
    
    Signed-off-by: Yasuhiro Matsumoto <[email protected]>
    Signed-off-by: Christian Brabandt <[email protected]>

diff --git a/src/testdir/test_vim9_cmd.vim b/src/testdir/test_vim9_cmd.vim
index b54a58b50..ce0589806 100644
--- a/src/testdir/test_vim9_cmd.vim
+++ b/src/testdir/test_vim9_cmd.vim
@@ -2094,6 +2094,24 @@ def Test_lambda_crash()
   v9.CheckScriptFailureList(lines, ["E1356:", "E1405:"])
 enddef
 
+def Test_skipped_lambda_after_else()
+  var lines =<< trim END
+    vim9script
+    def g:Warn(msg: string)
+      if has('patch-9.0.0321')
+        echo msg
+      else
+        timer_start(100, (_) => {
+          echohl WarningMsg | echom msg | echohl None
+        }, {repeat: 0})
+      endif
+    enddef
+    defcompile
+  END
+  v9.CheckScriptSuccess(lines)
+  delfunc! g:Warn
+enddef
+
 def s:check_previewpopup(expected_title: string)
   var id = popup_findpreview()
   assert_notequal(id, 0)
diff --git a/src/version.c b/src/version.c
index 78efc6c77..0c23e6a51 100644
--- a/src/version.c
+++ b/src/version.c
@@ -729,6 +729,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    448,
 /**/
     447,
 /**/
diff --git a/src/vim9expr.c b/src/vim9expr.c
index a6c4f1ea1..9d6033464 100644
--- a/src/vim9expr.c
+++ b/src/vim9expr.c
@@ -1741,6 +1741,29 @@ compile_tuple(
     return generate_NEWTUPLE(cctx, count, FALSE);
 }
 
+/*
+ * Restore "*arg" from a temporary cmdline copy.
+ */
+    static void
+restore_cmdline_arg(evalarg_T *evalarg, char_u **arg, cctx_T *cctx)
+{
+    garray_T    *gap;
+    char_u     *line;
+    size_t     off;
+
+    if (!evalarg->eval_using_cmdline || cctx == NULL)
+       return;
+
+    gap = &evalarg->eval_tofree_ga;
+    if (gap->ga_len == 0)
+       return;
+
+    off = *arg - ((char_u **)gap->ga_data)[gap->ga_len - 1];
+    line = ((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)[cctx->ctx_lnum];
+    *arg = line + off;
+    evalarg->eval_using_cmdline = FALSE;
+}
+
 /*
  * Parse a lambda: "(arg, arg) => expr"
  * "*arg" points to the '('.
@@ -1803,18 +1826,7 @@ compile_lambda(char_u **arg, cctx_T *cctx)
            compile_def_function(ufunc, FALSE, compile_type, cctx);
     }
 
-    // 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;
-       evalarg.eval_using_cmdline = FALSE;
-    }
+    restore_cmdline_arg(&evalarg, arg, cctx);
 
     clear_evalarg(&evalarg, NULL);
 
@@ -2348,6 +2360,7 @@ skip_expr_cctx(char_u **arg, cctx_T *cctx)
     init_evalarg(&evalarg);
     evalarg.eval_cctx = cctx;
     skip_expr(arg, &evalarg);
+    restore_cmdline_arg(&evalarg, arg, cctx);
     clear_evalarg(&evalarg, NULL);
 }
 

-- 
-- 
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 visit 
https://groups.google.com/d/msgid/vim_dev/E1wKgm1-00953g-UK%40256bit.org.

Raspunde prin e-mail lui