Commit: patch 9.2.0476: pattern completion leaks memory on alloc failures

2 views
Skip to first unread message

Christian Brabandt

unread,
May 12, 2026, 2:00:13 PM (7 days ago) May 12
to vim...@googlegroups.com
patch 9.2.0476: pattern completion leaks memory on alloc failures

Commit: https://github.com/vim/vim/commit/38237411e4e202a96b0efe41567505331114bfa8
Author: glepnir <gleph...@gmail.com>
Date: Tue May 12 17:40:19 2026 +0000

patch 9.2.0476: pattern completion leaks memory on alloc failures

Problem: copy_substring_from_pos() leaked on ga_grow() failures,
expand_pattern_in_buf() leaked "match" on ga_grow() failure,
fuzzy_match_str_with_pos() ignored ga_grow() failures
Solution: Route failures through cleanup paths, check ga_grow before
writing to ga_data (glepnir)

closes: #20203

Signed-off-by: glepnir <gleph...@gmail.com>
Signed-off-by: Christian Brabandt <c...@256bit.org>

diff --git a/src/cmdexpand.c b/src/cmdexpand.c
index f31398198..19ae31998 100644
--- a/src/cmdexpand.c
+++ b/src/cmdexpand.c
@@ -4914,7 +4914,7 @@ copy_substring_from_pos(pos_T *start, pos_T *end, char_u **match,
line = ml_get(lnum);
linelen = (int)ml_get_len(lnum);
if (ga_grow(&ga, linelen + 2) != OK)
- return FAIL;
+ goto fail;
ga_concat_len(&ga, line, linelen);
if (exacttext)
GA_CONCAT_LITERAL(&ga, "\n");
@@ -5141,8 +5141,8 @@ expand_pattern_in_buf(
}

// Extract the matching text prepended to completed word
- if (!copy_substring_from_pos(&cur_match_pos, &end_match_pos, &full_match,
- &word_end_pos))
+ if (copy_substring_from_pos(&cur_match_pos, &end_match_pos, &full_match,
+ &word_end_pos) == FAIL)
break;

if (exacttext)
@@ -5183,7 +5183,10 @@ expand_pattern_in_buf(
if (match != NULL)
{
if (ga_grow(&ga, 1) == FAIL)
+ {
+ VIM_CLEAR(match);
goto cleanup;
+ }
((char_u **)ga.ga_data)[ga.ga_len++] = match;
if (ga.ga_len > TAG_MANY)
break;
diff --git a/src/fuzzy.c b/src/fuzzy.c
index 9a94acea2..bb140fcac 100644
--- a/src/fuzzy.c
+++ b/src/fuzzy.c
@@ -690,7 +690,12 @@ fuzzy_match_str_with_pos(char_u *str UNUSED, char_u *pat UNUSED)
{
if (!VIM_ISWHITE(PTR2CHAR(p)))
{
- ga_grow(match_positions, 1);
+ if (ga_grow(match_positions, 1) == FAIL)
+ {
+ ga_clear(match_positions);
+ vim_free(match_positions);
+ return NULL;
+ }
((int_u *)match_positions->ga_data)[match_positions->ga_len] =
matches[j];
match_positions->ga_len++;
diff --git a/src/version.c b/src/version.c
index 9e794b7ed..6a8735c6b 100644
--- a/src/version.c
+++ b/src/version.c
@@ -729,6 +729,8 @@ static char *(features[]) =

static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 476,
/**/
475,
/**/
Reply all
Reply to author
Forward
0 new messages