vim-patch:9.1.2079: use-after-free with 'qftf' wiping buffer (#37364)

Problem:  use-after-free with 'quickfixtextfunc' wiping buffer
          (henices)
Solution: Evaluate 'quickfixtextfunc' with textlock enabled.

closes: vim/vim#19142

300ea1133f

Co-authored-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
zeertzjq
2026-01-12 07:04:36 +08:00
committed by GitHub
parent 1629493f72
commit aed1f8c377
5 changed files with 34 additions and 0 deletions

View File

@@ -4897,6 +4897,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.

View File

@@ -5115,6 +5115,9 @@ vim.go.pyx = vim.go.pyxversion
--- `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.
---

View File

@@ -6729,6 +6729,9 @@ local options = {
|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.
]=],

View File

@@ -4327,6 +4327,7 @@ static list_T *call_qftf_func(qf_list_T *qfl, int qf_winid, int start_idx, int e
args[0].v_type = VAR_DICT;
args[0].vval.v_dict = dict;
textlock++;
if (callback_call(cb, 1, args, &rettv)) {
if (rettv.v_type == VAR_LIST) {
qftf_list = rettv.vval.v_list;
@@ -4334,6 +4335,7 @@ static list_T *call_qftf_func(qf_list_T *qfl, int qf_winid, int start_idx, int e
}
tv_clear(&rettv);
}
textlock--;
tv_dict_unref(dict);
}

View File

@@ -6991,4 +6991,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