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,
/**/