]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.2.0724: Use-after-free when freeing exit_cb job on exit v9.2.0724
authorFoxe Chen <chen.foxe@gmail.com>
Wed, 24 Jun 2026 19:40:51 +0000 (19:40 +0000)
committerChristian Brabandt <cb@256bit.org>
Wed, 24 Jun 2026 19:40:51 +0000 (19:40 +0000)
Problem:  Use-after-free when freeing exit_cb job on exit
Solution: Return when def_functions has been freed already
          (Foxe Chen)

closes: #20621

Signed-off-by: Foxe Chen <chen.foxe@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
src/testdir/test_vim9_func.vim
src/version.c
src/vim9compile.c

index a2faec225d02d8dfebdd811e7b78c2792ca1a117..3774609c8096dfd08048ffb2de0a9e7cff3dbc14 100644 (file)
@@ -2,6 +2,7 @@
 
 import './util/vim9.vim' as v9
 source util/screendump.vim
+source util/shared.vim
 
 func Test_def_basic()
   def SomeFunc(): string
@@ -5045,4 +5046,27 @@ def Test_void_method_chain()
   v9.CheckScriptFailure(lines, 'E1186: Expression does not result in a value: bufload(')
 enddef
 
+def Test_term_wait_in_job_exit_cb()
+  CheckUnix
+  CheckFeature terminal
+
+  var cmd = g:GetVimCommand()
+
+  var lines =<< eval trim END
+      var buf: number = term_start(["{cmd}", "+q"], {{}})
+
+      var job: job = term_getjob(buf)
+
+      job_setoptions(job, {{
+      exit_cb: (_, _) => {{
+        term_wait(buf)
+          }}
+      }})
+  END
+
+  # This shouldn't cause an ASAN error immediately, but will result in a use
+  # after free when Vim exits.
+  v9.CheckDefSuccess(lines)
+enddef
+
 " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
index 43deacfd7a53d2c2a545e013589f3678e8e21fdd..010537fa1e5c214648fdc3b7443848332a67c67d 100644 (file)
@@ -759,6 +759,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    724,
 /**/
     723,
 /**/
index 181df2a6fb9758ea57ed474662bab645a406c356..3b1b9e9ef8f0915dce8de653e82bc5faf230345d 100644 (file)
@@ -5238,7 +5238,7 @@ delete_def_function_contents(dfunc_T *dfunc, int mark_deleted)
     void
 unlink_def_function(ufunc_T *ufunc)
 {
-    if (ufunc->uf_dfunc_idx <= 0)
+    if (ufunc->uf_dfunc_idx <= 0 || def_functions.ga_data == NULL)
        return;
 
     dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)