vim-patch:9.2.0331: spellfile: stack buffer overflows in spell file generation (#38948)

Problem:  spell_read_aff() uses sprintf() into a fixed-size stack buffer
          without bounds checking. store_aff_word() uses STRCAT() to
          append attacker-controlled strings into newword[MAXWLEN] without
          checking remaining space. Both are reachable via :mkspell with
          crafted .aff/.dic files (xinyi234)
Solution: Replace sprintf() with vim_snprintf() in spell_read_aff().
          Replace STRCAT() with STRNCAT() with explicit remaining-space
          calculation in store_aff_word().

closes: vim/vim#19944

07faa961a0

Co-authored-by: Christian Brabandt <cb@256bit.org>
(cherry picked from commit 4f7b6083e5)
This commit is contained in:
zeertzjq
2026-04-11 07:39:54 +08:00
committed by github-actions[bot]
parent 1a5d41a48f
commit e203257fff
2 changed files with 35 additions and 2 deletions

View File

@@ -2435,6 +2435,8 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char *fname)
char buf[MAXLINELEN];
aff_entry->ae_cond = getroom_save(spin, items[4]);
// Note: this silently truncates the buffer, but this should
// not happen in practice
snprintf(buf, sizeof(buf), *items[0] == 'P' ? "^%s" : "%s$", items[4]);
aff_entry->ae_prog = vim_regcomp(buf, RE_MAGIC + RE_STRING + RE_STRICT);
if (aff_entry->ae_prog == NULL) {
@@ -3389,7 +3391,9 @@ static int store_aff_word(spellinfo_T *spin, char *word, char *afflist, afffile_
MB_PTR_ADV(p);
}
}
strcat(newword, p);
// Note: this silently truncates the buffer, but this should
// not happen in practice
xstrlcat(newword, p, MAXWLEN);
} else {
// suffix: chop/add at the end of the word
xstrlcpy(newword, word, MAXWLEN);
@@ -3403,7 +3407,9 @@ static int store_aff_word(spellinfo_T *spin, char *word, char *afflist, afffile_
*p = NUL;
}
if (ae->ae_add != NULL) {
strcat(newword, ae->ae_add);
// Note: this silently truncates the buffer, but this should
// not happen in practice
xstrlcat(newword, ae->ae_add, MAXWLEN);
}
}