vim-patch:9.2.0960: double-free in string_reduce() (#41357)

Problem:  string_reduce() copies *rettv into argv[0] before calling
          eval_expr_typval().  When the evaluator fails early, rettv is
          never reset and still aliases argv[0] v_string.
          clear_tv(&argv[0]) frees it, leaving rettv dangling and when
          in vim9script get_func_tv() frees it again (Ave Dva).
Solution: Set rettv->v_type = VAR_UNKNOWN like what is done in
          list_reduce() and tuple_reduce(), use tv_get_string_strict()
          in f_reduce()

closes: vim/vim#21048

Supported by AI.

cd59994c45

Co-authored-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
zeertzjq
2026-08-18 09:03:27 +08:00
committed by GitHub
parent b107154ba2
commit cc25b2f13c
2 changed files with 9 additions and 0 deletions

View File

@@ -5321,6 +5321,7 @@ static void reduce_string(typval_T *argvars, typval_T *expr, typval_T *rettv)
for (; *p != NUL; p += len) {
typval_T argv[3];
argv[0] = *rettv;
rettv->v_type = VAR_UNKNOWN;
len = utfc_ptr2len(p);
argv[1] = (typval_T){
.v_type = VAR_STRING,

View File

@@ -1066,6 +1066,14 @@ func Test_reduce()
" call assert_fails('echo reduce([1], test_null_function())', 'E1132:')
" Nvim doesn't have null partials
" call assert_fails('echo reduce([1], test_null_partial())', 'E1132:')
" did cause double free
function! OuterReduce()
vim9 echo reduce('ab', 42)
endfunction
"call assert_fails('call OuterReduce()', 'E1024:')
call assert_fails("echo reduce('ab', 'NoSuchFunc')", 'E117:')
delfunc OuterReduce
endfunc
" splitting a string to a List using split()