Vim 9.2.0321 stack-buffer-overflows Vulnerability report
Vim 9.2.0321 stack-buffer-overflows Vulnerability report
- Severity: Medium
- Affected Versions: Vim 9.2.0321
Overview
Attacker-controlled spell source files can trigger multiple stack-based buffer overflows in Vim’s spell file generation path during :mkspell. I confirmed two related vulnerabilities in spellfile.c: one in spell_read_aff() and one in store_aff_word(). Both are reachable from crafted .aff / .dic inputs, both involve attacker-controlled spell data being written into fixed-size stack buffers without sufficient bounds enforcement, and both can crash Vim in the tested environment. I have not verified exploitability beyond denial of service.
Vulnerability Type
- CWE-121: Stack-Based Buffer Overflow
Details
I reproduced these issues on Vim 9.2.0321 while processing attacker-controlled spell source files through the :mkspell path.
1. stack-buffer-overflow in spell_read_aff()
The first issue occurs in spell_read_aff(), where attacker-controlled affix rule content is formatted with sprintf() into a fixed-size stack buffer.
Relevant locations:
spellfile.c:2736— fixed-size stack bufferspellfile.c:2742—sprintf()write sitespellfile.c:6065—mkspell()path reachingspell_read_aff()spellfile.c:5464—ex_mkspell()caller path
In the reproduced case, the .aff file declares SET ISO8859-1, while Vim is run with encoding=utf-8. This causes character-set conversion to increase the effective length of the attacker-controlled content before it is written into the vulnerable stack buffer.
AddressSanitizer reports a stack-buffer-overflow at the sprintf() write site. The ASan report also shows that the target stack object buf occupies offsets [1024, 1524), while the invalid write begins at offset 1524, confirming that the sprintf() output overruns the end of that fixed-size stack buffer.
Relevant crash excerpt:
1 | ==73524==ERROR: AddressSanitizer: stack-buffer-overflow on address ... |
2. stack-buffer-overflow in store_aff_word()
The second issue occurs in store_aff_word(), which also operates on attacker-controlled spell data during :mkspell.
Relevant locations:
spellfile.c:3834—char_u newword[MAXWLEN]spellfile.c:3909—STRCAT(newword, p)in the prefix-handling pathspellfile.c:3925—STRCAT(newword, ae->ae_add)in the suffix-handling pathspellfile.c:3673—spell_read_dic()callingstore_aff_word()spellfile.c:6073—mkspell()path reachingspell_read_dic()
In both concatenation paths, newword is first populated with truncated content via vim_strncpy(..., MAXWLEN - 1), and then a second attacker-controlled component is appended with STRCAT() without checking whether the final combined length still fits in MAXWLEN.
I reproduced the suffix-path variant with a crafted .aff and .dic pair. At a GDB breakpoint on spellfile.c:3925, the runtime values were:
strlen(newword) = 253strlen(ae->ae_add) = 400
This confirms that the code reaches STRCAT(newword, ae->ae_add) with a 253-byte destination string and a 400-byte append string, which exceeds the MAXWLEN-sized stack buffer.
The runtime crash evidence also shows Program received signal SIGSEGV in store_aff_word() and a corrupted backtrace with repeated 0xc3bfc3bfc3bfc3bf values, consistent with attacker-controlled UTF-8-expanded bytes having smashed stack state after the unsafe concatenation.
Relevant GDB excerpts:
1 | Breakpoint 1, store_aff_word (...) at spellfile.c:3925 |
1 | Program received signal SIGSEGV, Segmentation fault. |
Root-cause relationship
These two vulnerabilities are closely related:
- both are in
spellfile.c - both are reachable during
:mkspell - both process attacker-controlled spell inputs from
.aff/.dic - both become especially dangerous when character-set conversion expands the effective input length
- both write attacker-influenced content into fixed-size stack buffers without validating the final combined length
For that reason, I am reporting them together as related stack-overflow vulnerabilities in the spell generation pipeline.
PoC
PoC 1 — spell_read_aff()
Create poc.aff:
1 | SET ISO8859-1 |
Create poc.dic:
1 | 1 |
Trigger command:
1 | vim -Nu NONE -n -es -X \ |
Observed result:
- Vim aborts with exit code
134 - AddressSanitizer reports
stack-buffer-overflowinspell_read_aff()
PoC 2 — store_aff_word()
Create poc_sfx.aff with a long attacker-controlled add-string and poc_sfx.dic with a long attacker-controlled word using the same affix flag. In the reproduced case, both inputs contain 200 bytes of 0xFF, the affix file declares SET ISO8859-1, and Vim is run with encoding=utf-8, causing both sides to expand before concatenation in store_aff_word().
Example structure:
1 | poc_sfx.aff: |
Reproduction command:
1 | vim -Nu NONE -n -es -X \ |
Observed result in the reproduced environment:
mkspellexits with code139- GDB shows
Program received signal SIGSEGV - The crash occurs in
store_aff_word() - At
spellfile.c:3925, the runtime lengths reachstrlen(newword) = 253andstrlen(ae->ae_add) = 400beforeSTRCAT(newword, ae->ae_add)

Impact
These are stack-based buffer overflows (CWE-121) in Vim’s spell file generation pipeline during :mkspell.
In the tested environment:
spell_read_aff()is confirmed to trigger an AddressSanitizer-detected stack-buffer-overflow and a deterministic crashstore_aff_word()is confirmed to trigger a segmentation fault with runtime evidence showing unsafe concatenation beyond the bounds ofnewword[MAXWLEN]
The practical impact I have confirmed is denial of service when Vim processes attacker-controlled spell source files (.aff / .dic) through :mkspell. I have not verified exploitability beyond DoS.


