From: Foxe Chen Date: Wed, 24 Jun 2026 19:40:51 +0000 (+0000) Subject: patch 9.2.0724: Use-after-free when freeing exit_cb job on exit X-Git-Tag: v9.2.0724^0 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1ccf3388dc950aab43330035d5d0daeb80536b8f;p=thirdparty%2Fvim.git 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 Signed-off-by: Christian Brabandt --- diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim index a2faec225d..3774609c80 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 43deacfd7a..010537fa1e 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 181df2a6fb..3b1b9e9ef8 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)