GHSA-m3hf-xcm3-xhm2 on CTRL-OS 26.05
Aliases: GHSA-m3hf-xcm3-xhm2, CVE-2026-59857
Packages: vim
Status: Plausible
Advisory Information
Out-of-bounds Write in SAL Soundfolding in Vim < 9.2.0725
Date: 24.06.2026 Severity: Medium CVE: CVE-2026-59857 CWE: Out-of-bounds Write (CWE-787)
Summary
The single-byte branch of
spell_soundfold_sal()insrc/spell.ctranslates a word through a spell file's SAL (sound-folding) rules into a caller-owned result buffer. Its result writes are guarded withreslen < MAXWLEN, which allowsreslento reachMAXWLEN. The function then terminates the result withres[reslen] = NUL, writing one byte past the end of theMAXWLEN-element stack buffer whenreslen == MAXWLEN. A word that reaches the buffer boundary, passed tosoundfold()(or reached via sound-based spell suggestion) while a SAL-based spell language is active, therefore writes past the end of that buffer. This is a stack out-of-bounds write that corrupts the call frame and crashes the editor.Description
spell_soundfold_sal()writes its translated output into the stack bufferres, an array of size[MAXWLEN](valid indices0..MAXWLEN - 1). The single-byte branch, taken for 8-bit encodings such aslatin1, guards each result write withreslen < MAXWLEN, soreslencan be incremented up to and includingMAXWLEN. After the translation loop the result is NUL-terminated:res[reslen] = NUL; // reslen may equal MAXWLEN -> OOB writeWith
reslen == MAXWLENthis stores at indexMAXWLENof aMAXWLEN-element buffer, one byte past the end (CWE-787). The preceding write sites in this branch — the no-<-rule copy loop, the"^^"rule append, and the double-letter condense — are bounded with< MAXWLENrather than< MAXWLEN - 1, leaving no room for the terminating NUL at the boundary.
f_soundfold()passes the user-supplied string toeval_soundfold()without length-bounding it; the input is case-folded to roughlyMAXWLEN - 1bytes, so an argument at that boundary length drivesreslentoMAXWLEN. This is the SAL counterpart to the SOFO issue fixed in 9.2.0698; the single-byte SAL branch was the remaining walker of this class with an off-by-one at the terminator.Impact
This issue is driven by the length of the word handed to the
spell_soundfold_sal()function, not by the contents of the spell file; any loaded spell language with SAL sound-folding rules is enough. Exploitation is constrained, however. The vulnerable single-byte branch is only reached under a non-multibyte 8-bit encoding (e.g.set encoding=latin1); under the default UTF-8 encoding the multibyte branchspell_soundfold_wsal(), which writes one full character at a time and breaks onl + MB_MAXBYTES > MAXWLEN, is taken instead and is unaffected. Spell checking must be enabled with such a SAL-based language, andsoundfold()must be invoked on a boundary-length word — for instance a script or plugin that callssoundfold()on untrusted input. When those conditions hold the out-of-bounds write corrupts theeval_soundfold()stack frame and the process aborts.Acknowledgements
The Vim project would like to thank Hirohito Higashi (@h-east) for reporting and analyzing the issue and suggesting a fix.
References
The issue has been fixed as of Vim patch v9.2.0725. - Commit - Github Security Advisory
Updates
2026-07-10 22:53 CEST
Metadata changes:
- Status for package
vim: “Plausible”
2026-07-06 22:42 CEST
Metadata changes:
- Status for package
vim: “New”