From ba0e5b25bcaf307019b619db25bd19c78bb59846 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 25 Jul 2026 07:00:11 +0800 Subject: [PATCH] vim-patch:9.2.0846: [security]: heap buffer overflow in set_sofo() Problem: [security]: heap buffer overflow in set_sofo() (Yazan Balawneh) Solution: Reset sl_sal_first (Yasuhiro Matsumoto). A crafted spell file with an empty SN_SAL section before an SN_SOFO section reaches set_sofo() with sl_sal_first[] already set to -1 by set_sal_first(). The counting loop then under-counts colliding multi-byte "from" characters, allocates an undersized list and writes past its end. Github Security Advisory: https://github.com/vim/vim/security/advisories/GHSA-9jqx-hgpr-6v64 https://github.com/vim/vim/commit/05c41c922309c7a11b6ec2f124be66551c90d66a Co-authored-by: Yasuhiro Matsumoto --- src/nvim/spellfile.c | 4 +++- test/old/testdir/test_spellfile.vim | 5 +++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/nvim/spellfile.c b/src/nvim/spellfile.c index 466aaf4578..f934b9f94e 100644 --- a/src/nvim/spellfile.c +++ b/src/nvim/spellfile.c @@ -1553,7 +1553,9 @@ static int set_sofo(slang_T *lp, const char *from, const char *to) lp->sl_sofo = true; // First count the number of items for each list. Temporarily use - // sl_sal_first[] for this. + // sl_sal_first[] for this. Reset it first: a preceding SN_SAL section + // may have set the entries to -1 via set_sal_first(). + memset(lp->sl_sal_first, 0, sizeof(salfirst_T) * 256); for (p = from, s = to; *p != NUL && *s != NUL;) { const int c = mb_cptr2char_adv(&p); s += utf_ptr2len(s); diff --git a/test/old/testdir/test_spellfile.vim b/test/old/testdir/test_spellfile.vim index 0938e4cfd1..9919821a6f 100644 --- a/test/old/testdir/test_spellfile.vim +++ b/test/old/testdir/test_spellfile.vim @@ -322,6 +322,11 @@ func Test_spellfile_format_error() " SN_SOFO: multi-byte characters in sofofrom and sofoto call Spellfile_Test(0z0600000000080002CF810002CF82FF000000000000000000000000, '') + " SN_SAL (empty) followed by SN_SOFO with two multi-byte 'from' characters + " sharing the same low byte. A preceding SN_SAL poisons sl_sal_first[], so + " without a reset set_sofo() under-counts and writes out of bounds. + call Spellfile_Test(0z05000000000300000006000000000A0004CAABCEAB00024142FF000000000000000000000000, '') + " SN_COMPOUND: compmax is less than 2 call Spellfile_Test(0z08000000000101, 'E759:')