patch 9.2.0780: Memory leak in evalvars.c on alloc failure
Commit:
https://github.com/vim/vim/commit/f2156161c52548af2a502858b59f48ea2fb33bb2
Author: Christian Brabandt <
c...@256bit.org>
Date: Thu Jul 2 20:06:33 2026 +0000
patch 9.2.0780: Memory leak in evalvars.c on alloc failure
Problem: Memory leak in evalvars.c on alloc failure (Ao Xijie)
Solution: free new_tuple when tuple_append_tv() fails and clear typeval,
add a test.
closes: #20668
Supported by AI.
Signed-off-by: Christian Brabandt <
c...@256bit.org>
diff --git a/src/alloc.h b/src/alloc.h
index f3a27f621..3d740bca3 100644
--- a/src/alloc.h
+++ b/src/alloc.h
@@ -46,5 +46,6 @@ typedef enum {
aid_blob_alloc,
aid_get_func,
aid_defer,
+ aid_tuple_append,
aid_last
} alloc_id_T;
diff --git a/src/evalvars.c b/src/evalvars.c
index 9b98ae731..f74b1c76a 100644
--- a/src/evalvars.c
+++ b/src/evalvars.c
@@ -1363,7 +1363,11 @@ ex_let_vars(
copy_tv(TUPLE_ITEM(tuple, idx), &new_tv);
if (tuple_append_tv(new_tuple, &new_tv) == FAIL)
+ {
+ clear_tv(&new_tv);
+ tuple_unref(new_tuple);
return FAIL;
+ }
idx++;
}
diff --git a/src/testdir/test_tuple.vim b/src/testdir/test_tuple.vim
index 26609a20f..68bdca08c 100644
--- a/src/testdir/test_tuple.vim
+++ b/src/testdir/test_tuple.vim
@@ -2463,4 +2463,12 @@ func Test_tuple_multi_assign_in_for_loop_from_import()
call v9.CheckSourceScriptSuccess(lines)
endfunc
+" Memory allocation failure while collecting the rest of a tuple in an unpack
+func Test_tuple_unpack_memory_fail()
+ let t = ('1', '2', '3')
+ call test_alloc_fail(GetAllocId('tuple_append'), 0, 0)
+ call assert_fails('let [a; rest] = t', 'E342:')
+ unlet t
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/tuple.c b/src/tuple.c
index b7a420e94..8e5a9fcfa 100644
--- a/src/tuple.c
+++ b/src/tuple.c
@@ -291,7 +291,7 @@ tuple_find(tuple_T *tuple, long n)
int
tuple_append_tv(tuple_T *tuple, typval_T *tv)
{
- if (ga_grow(&tuple->tv_items, 1) == FAIL)
+ if (ga_grow_id(&tuple->tv_items, 1, aid_tuple_append) == FAIL)
return FAIL;
tuple_set_item(tuple, TUPLE_LEN(tuple), tv);
diff --git a/src/version.c b/src/version.c
index 1d6c351a7..27c2bfe52 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 */
+/**/
+ 780,
/**/
779,
/**/