patch 9.2.0724: Use-after-free when freeing exit_cb job on exit
Commit:
https://github.com/vim/vim/commit/1ccf3388dc950aab43330035d5d0daeb80536b8f
Author: Foxe Chen <
chen...@gmail.com>
Date: Wed Jun 24 19:40:51 2026 +0000
patch 9.2.0724: Use-after-free when freeing exit_cb job on exit
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...@gmail.com>
Signed-off-by: Christian Brabandt <
c...@256bit.org>
diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim
index a2faec225..3774609c8 100644
--- a/src/testdir/test_vim9_func.vim
+++ b/src/testdir/test_vim9_func.vim
@@ -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
diff --git a/src/version.c b/src/version.c
index 43deacfd7..010537fa1 100644
--- a/src/version.c
+++ b/src/version.c
@@ -759,6 +759,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 724,
/**/
723,
/**/
diff --git a/src/vim9compile.c b/src/vim9compile.c
index 181df2a6f..3b1b9e9ef 100644
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -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)