Commit: patch 9.2.0960: double-free in string_reduce()
Christian Brabandt <[email protected]>
| Newsgroups | gmane.editors.vim.devel |
|---|---|
| Message-ID | <[email protected]> |
patch 9.2.0960: double-free in string_reduce() Commit: https://github.com/vim/vim/commit/cd59994c455a20d39d5cc41b4978ecfd2bf4be2e Author: Christian Brabandt <[email protected]> Date: Mon Aug 17 19:05:55 2026 +0000 patch 9.2.0960: double-free in string_reduce() 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: #21048 Supported by AI. Signed-off-by: Christian Brabandt <[email protected]> diff --git a/src/list.c b/src/list.c index cf5374de2..0ea2e13bd 100644 --- a/src/list.c +++ b/src/list.c @@ -3472,7 +3472,7 @@ f_reduce(typval_T *argvars, typval_T *rettv) else if (argvars[1].v_type == VAR_PARTIAL) func_name = partial_name(argvars[1].vval.v_partial); else - func_name = tv_get_string(&argvars[1]); + func_name = tv_get_string_strict(&argvars[1]); if (func_name == NULL || *func_name == NUL) { emsg(_(e_missing_function_argument)); diff --git a/src/strings.c b/src/strings.c index 71f9d83e2..fa24586c1 100644 --- a/src/strings.c +++ b/src/strings.c @@ -1043,9 +1043,14 @@ string_reduce( for ( ; *p != NUL; p += len) { argv[0] = *rettv; + rettv->v_type = VAR_UNKNOWN; + len = copy_first_char_to_tv(p, &argv[1]); if (len < 0) + { + *rettv = argv[0]; break; + } r = eval_expr_typval(expr, TRUE, argv, 2, fc, rettv); diff --git a/src/testdir/test_listdict.vim b/src/testdir/test_listdict.vim index 31b5f268d..88c2e07bd 100644 --- a/src/testdir/test_listdict.vim +++ b/src/testdir/test_listdict.vim @@ -1115,6 +1115,14 @@ func Test_reduce() " should not crash call assert_fails('echo reduce([1], test_null_function())', 'E1132:') 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() diff --git a/src/version.c b/src/version.c index 65bfaa6f0..19542bdde 100644 --- a/src/version.c +++ b/src/version.c @@ -763,6 +763,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 960, /**/ 959, /**/ -- -- You received this message from the "vim_dev" maillist. Do not top-post! Type your reply below the text you are replying to. For more information, visit http://www.vim.org/maillist.php --- You received this message because you are subscribed to the Google Groups "vim_dev" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To view this discussion visit https://groups.google.com/d/msgid/vim_dev/E1ww2na-008wKi-TY%40256bit.org.