patch 9.1.2079: use-after-free with 'qftf' wiping buffer
Commit:
https://github.com/vim/vim/commit/300ea1133fba310ae8acd7fadc3ab3cc24e8402f
Author: Christian Brabandt <
c...@256bit.org>
Date: Sun Jan 11 19:06:31 2026 +0000
patch 9.1.2079: use-after-free with 'qftf' wiping buffer
Problem: use-after-free with 'quickfixtextfunc' wiping buffer
(henices)
Solution: Evaluate 'quickfixtextfunc' with textlock enabled.
closes: #19142
Signed-off-by: Christian Brabandt <
c...@256bit.org>
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index aa9cff62d..1dfb8d6f8 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -6973,6 +6973,9 @@ A jump table for the options with a short description can be found at |Q_op|.
|lambda| or a |Funcref|. See |option-value-function| for more
information.
+ It is not allowed to change text or jump to another window while
+ evaluating 'qftf' |textlock|.
+
This option cannot be set from a |modeline| or in the |sandbox|, for
security reasons.
diff --git a/src/quickfix.c b/src/quickfix.c
index 07e0b7aa1..87b154dbb 100644
--- a/src/quickfix.c
+++ b/src/quickfix.c
@@ -5097,6 +5097,7 @@ call_qftf_func(qf_list_T *qfl, int qf_winid, long start_idx, long end_idx)
args[0].vval.v_dict = d;
qftf_list = NULL;
+ textlock++;
if (call_callback(cb, 0, &rettv, 1, args) != FAIL)
{
if (rettv.v_type == VAR_LIST)
@@ -5106,6 +5107,7 @@ call_qftf_func(qf_list_T *qfl, int qf_winid, long start_idx, long end_idx)
}
clear_tv(&rettv);
}
+ textlock--;
dict_unref(d);
}
diff --git a/src/testdir/test_quickfix.vim b/src/testdir/test_quickfix.vim
index 6e939a653..4c61b6b2e 100644
--- a/src/testdir/test_quickfix.vim
+++ b/src/testdir/test_quickfix.vim
@@ -6969,4 +6969,27 @@ func Test_quickfix_restore_current_win()
bw! Xb
endfunc
+func Test_quickfixtextfunc_wipes_buffer()
+ let g:crash=""
+ new
+ fu QFexpr(dummy)
+ bw
+ endfu
+ try
+ set quickfixtextfunc=QFexpr
+ lad "['0:4:e']"
+ lw
+ catch /^Vim\%((\S\+)\)\=:E565:/
+ let g:crash='caught'
+ endtry
+ " close location list window
+ bw
+ delfunc QFexpr
+ set quickfixtextfunc=
+ call assert_equal('caught', g:crash)
+ unlet g:crash
+ " close the newly opened window
+ bw
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/version.c b/src/version.c
index 0e048c40f..c7d7e87e5 100644
--- a/src/version.c
+++ b/src/version.c
@@ -734,6 +734,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 2079,
/**/
2078,
/**/