Re: [LFS Trac] #5956: vim-9.2.0699 (Security Update) (was: vim-9.2.0679 (Security Update))

LFS Trac ([email protected] via lfs-book Mailing List) <[email protected]> Mon, 22 Jun 2026 19:24:33 -0000
Newsgroups gmane.linux.lfs.book
Message-ID <[email protected]>
#5956: vim-9.2.0699 (Security Update)
-------------------------+-----------------------
 Reporter:  Joe Locash   |       Owner:  lfs-book
     Type:  enhancement  |      Status:  new
 Priority:  normal       |   Milestone:  13.1
Component:  Book         |     Version:  git
 Severity:  normal       |  Resolution:
 Keywords:               |
-------------------------+-----------------------
Changes (by Joe Locash):

 * summary:  vim-9.2.0679 (Security Update) => vim-9.2.0699 (Security
              Update)

Comment:

 {{{
 Out-of-bounds Write in SOFO Soundfolding in Vim < 9.2.0698
 ==========================================================
 Date: 21.06.2026
 Severity: Medium
 CVE: *requested, not yet assigned*
 CWE: Out-of-bounds Write (CWE-787)

 ## Summary
 The single-byte branch of `spell_soundfold_sofo()` in `src/spell.c`
 translates
 a word through a spell file's SOFO (sound-folding) byte map into a caller-
 owned
 result buffer.  Its copy loop advances the output index `ri` with no upper
 bound and terminates only on the input NUL, writing one byte per input
 byte
 into the `MAXWLEN`-element stack buffer the caller provides.  A word
 longer
 than `MAXWLEN`, passed to `soundfold()` (or reached via sound-based spell
 suggestion) while a SOFO-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_sofo()` has two branches.  The multibyte branch (taken
 under
 multibyte encodings) bounds its output with `if (ri + MB_MAXBYTES >
 MAXWLEN)
 break;`.  The single-byte branch, taken for 8-bit encodings such as
 `latin1`,
 has no equivalent guard:

 ```C
     else
     {
         // The sl_sal_first[] table contains the translation.
         for (s = inword; (c = *s) != NUL; ++s)      // bound: input NUL
 only
         {
             if (VIM_ISWHITE(c))
                 c = ' ';
             else
                 c = slang->sl_sal_first[c];
             if (c != NUL && (ri == 0 || res[ri - 1] != c))
                 res[ri++] = c;                      // no ri < MAXWLEN
 guard
         }
     }
     res[ri] = NUL;                                  // trailing OOB write
 too
 ```

 The destination `res` is an array of size `[MAXWLEN]`. `f_soundfold()`
 passes
 the user-supplied string straight to `eval_soundfold()` without length-
 bounding
 it, so once the active language carries a SOFO map (`sl_sal_first`), any
 input
 longer than 253 bytes runs `ri` past the end of the buffer.  The two
 sibling
 walkers do bound their output (`spell_soundfold_sal()` truncates its input
 with
 `vim_strncpy(.., MAXWLEN - 1)` and guards `reslen < MAXWLEN`;
 `spell_soundfold_wsal()` guards `reslen < MAXWLEN`); the single-byte SOFO
 branch was the remaining unguarded walker of this class.

 ## Impact
 This issue is driven by the length of the word handed to the
 spell_soundfold_sofo() function, not by the contents of the spell file.
 any
 loaded spell language with a SOFO sound-folding table 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 branch, which is already bounded, is
 taken
 instead.  Spell checking must be enabled with such a SOFO-based language,
 and
 `soundfold()`  must be invoked on an over-long word - for instance a
 script or
 plugin that calls `soundfold()` on untrusted input.  When those conditions
 hold
 the out-of-bounds write corrupts the `eval_soundfold()` stack frame and
 the
 process aborts.

 ## Acknowledgements
 The Vim project would like to thank Cipher / Causal Security
 (https://causalsecurity.com/) for reporting and analyzing the issue and
 suggesting a fix.

 ## References
 The issue has been fixed as of Vim patch
 [v9.2.0698](https://github.com/vim/vim/releases/tag/v9.2.0698).
 -
 [Commit](https://github.com/vim/vim/commit/497f931f85339d175d7f69588dd249e8ccfed41b)
 - [Github Security
 Advisory](https://github.com/vim/vim/security/advisories/GHSA-q8mh-
 6qm3-25g4)
 }}}

 {{{
 Arbitrary Code Execution via Python Omni-Completion Docstrings in Vim <
 9.2.0699
 ================================================================================
 Date: 2026-06-21
 Severity: Medium
 CVE: *requested, not yet assigned*
 CWE: Improper Control of Generation of Code (CWE-94)

 ## Summary
 Vim's Python omni-completion executes reconstructed function and class
 definitions from the current buffer with `exec()` as part of populating
 the
 completion dictionary. When reconstructing that source, each scope's
 docstring
 is inserted verbatim between triple quotes with no escaping, so a hostile
 buffer can break out of the triple-quoted literal and execute attacker-
 controlled Python during omni-completion. This is the same class of issue
 as
 GHSA-65p9-mwwx-7468 (patch 9.2.0597), whose fix sanitised parameter
 defaults/annotations and class base lists but left the docstring path
 untouched.

 ## Description
 In `runtime/autoload/python3complete.vim` (and the legacy
 `pythoncomplete.vim`), the `get_code()` methods build the source later
 passed
 to `exec()` and emit each docstring as `'"""' + self.docstr + '"""'`.
 `self.docstr` comes straight from buffer content, and the `doc()` helper
 only
 strips leading and trailing quote and whitespace characters, so a `"""`
 embedded in the middle of a docstring survives. A class-body docstring
 written
 as a single-quoted source string keeps the embedded `"""` as one string
 token
 through `doc()`, then breaks out of the generated triple-quoted literal:
 the
 reconstructed `class` body becomes string concatenation around an attacker
 expression, which Python evaluates at class-definition time when `exec()`
 runs.

 ## Impact
 An attacker who can convince a user to open or edit a hostile Python
 buffer and trigger Python omni-completion (CTRL-X CTRL-O, or a plugin
 that invokes the completion function) can execute Python code in the
 user's Vim process. The code runs with the user's privileges.

 Vim built without `+python3` and `+python` is not affected. Triggering
 omni-completion in the hostile buffer is required; opening the file
 alone is not sufficient.

 ## Acknowledgements
 The Vim project would like to thank Chenyuan Mi for reporting and
 analyzing the
 issue and suggesting a fix.

 ## References
 The issue has been fixed as of Vim patch
 [v9.2.0699](https://github.com/vim/vim/releases/tag/v9.2.0699).
 -
 [Commit](https://github.com/vim/vim/commit/cce141c42740f122dd8486ae04e21c2a81016ba8)
 - [Github Security
 Advisory](https://github.com/vim/vim/security/advisories/GHSA-ppj8-wqjf-
 6fp3)
 - [Github Security Advisory GHSA-
 65p9-mwwx-7468](https://github.com/vim/vim/security/advisories/GHSA-
 65p9-mwwx-7468) (prior fix for the same surface)

 }}}
-- 
Ticket URL: <https://wiki.linuxfromscratch.org/lfs/ticket/5956#comment:3>
LFS Trac <https://wiki.linuxfromscratch.org/lfs/>
Linux From Scratch: Your Distro, Your Rules.

-- 
http://lists.linuxfromscratch.org/sympa/info/lfs-book
Unsubscribe: See the above information page