From 636b8cbcfc76e884b4421d1a327fbd8ddfdd32ce Mon Sep 17 00:00:00 2001 From: RHEL Packaging Agent Date: Wed, 29 Jul 2026 13:57:18 +0000 Subject: [PATCH] Fix CVE-2026-59858: arbitrary Ex command execution in C omni-completion Backport upstream fix for CVE-2026-59858 from commit 6b611b0d15603c52ebdad17172b0232b4f65704e. A crafted tags file could execute arbitrary Ex commands when completing struct/union members via C omni-completion. The fix escapes the typename field before interpolating it into the :vimgrep pattern in StructMembers(), preventing command injection. A new test file validates both the security fix and that normal struct-member completion continues to work. CVE: CVE-2026-59858 Upstream patches: - https://github.com/vim/vim/commit/6b611b0d15603c52ebdad17172b0232b4f65704e.patch - https://github.com/vim/vim/commit/d9ec67691170cd3764cbf767636305e47987340f Resolves: RHEL-203886 --- ...ecurity-arbitrary-Ex-command-executi.patch | 127 ++++++++++++++++++ ...me-ccomplete-fix-type-mismatch-error.patch | 30 +++++ vim.spec | 14 +- 3 files changed, 170 insertions(+), 1 deletion(-) create mode 100644 0001-patch-9.2.0735-security-arbitrary-Ex-command-executi.patch create mode 100644 0001-runtime-ccomplete-fix-type-mismatch-error.patch diff --git a/0001-patch-9.2.0735-security-arbitrary-Ex-command-executi.patch b/0001-patch-9.2.0735-security-arbitrary-Ex-command-executi.patch new file mode 100644 index 00000000..f3de55c5 --- /dev/null +++ b/0001-patch-9.2.0735-security-arbitrary-Ex-command-executi.patch @@ -0,0 +1,127 @@ +From 65007bcf94a8c32ce99fbbb69c71124e4a06f580 Mon Sep 17 00:00:00 2001 +From: Hirohito Higashi +Date: Fri, 26 Jun 2026 15:41:24 +0900 +Subject: [PATCH] patch 9.2.0735: [security]: arbitrary Ex command execution + during C omni-completion + +Problem: [security]: With C omni-completion, a crafted tags file can execute + arbitrary Ex commands when completing a struct/union member + (cipher-creator) +Solution: Escape the type field before inserting it into the :vimgrep + pattern so it cannot close the pattern and start a new command + (Hirohito Higashi). + +Github Security Advisory: +https://github.com/vim/vim/security/advisories/GHSA-mf92-v4xw-j45x + +Co-Authored-By: Claude Opus 4.8 (1M context) " +Signed-off-by: Hirohito Higashi +Signed-off-by: Christian Brabandt +--- + runtime/autoload/ccomplete.vim | 2 +- + src/testdir/Make_all.mak | 2 + + src/testdir/test_plugin_ccomplete.vim | 62 +++++++++++++++++++++++++++ + 3 files changed, 65 insertions(+), 1 deletion(-) + create mode 100644 src/testdir/test_plugin_ccomplete.vim + +diff --git a/runtime/autoload/ccomplete.vim b/runtime/autoload/ccomplete.vim +index 7096dcf4a..fa69f57eb 100644 +--- a/runtime/autoload/ccomplete.vim ++++ b/runtime/autoload/ccomplete.vim +@@ -560,7 +560,7 @@ def StructMembers( # {{{1 + if !cached + while 1 + execute 'silent! keepjumps noautocmd ' +- .. n .. 'vimgrep ' .. '/\t' .. typename .. '\(\t\|$\)/j ' ++ .. n .. 'vimgrep ' .. '/\t' .. escape(typename, '/\') .. '\(\t\|$\)/j ' + .. fnames + + qflist = getqflist() +diff --git a/src/testdir/Make_all.mak b/src/testdir/Make_all.mak +index c4df6ec27..abcdef123 100644 +--- a/src/testdir/Make_all.mak ++++ b/src/testdir/Make_all.mak +@@ -227,6 +227,7 @@ NEW_TESTS = \ + test_partial \ + test_paste \ + test_perl \ ++ test_plugin_ccomplete \ + test_plugin_phpcomplete \ + test_plugin_tar \ + test_plus_arg_edit \ +@@ -479,6 +480,7 @@ NEW_TESTS_RES = \ + test_partial.res \ + test_paste.res \ + test_perl.res \ ++ test_plugin_ccomplete.res \ + test_plugin_phpcomplete.res \ + test_plugin_tar.res \ + test_plus_arg_edit.res \ +diff --git a/src/testdir/test_plugin_ccomplete.vim b/src/testdir/test_plugin_ccomplete.vim +new file mode 100644 +index 000000000..a635bd50b +--- /dev/null ++++ b/src/testdir/test_plugin_ccomplete.vim +@@ -0,0 +1,62 @@ ++" Tests for the C omni-completion plugin (runtime/autoload/ccomplete.vim). ++ ++func s:WriteTags(lines) ++ " Mark unsorted so lookup is a linear scan regardless of entry order. ++ let tagsfile = tempname() ++ call writefile(["!_TAG_FILE_SORTED\t0\t/0/"] + a:lines, tagsfile) ++ return tagsfile ++endfunc ++ ++" A crafted typeref field is interpolated into the :vimgrep pattern in ++" StructMembers(). Without escaping, "/" closes the pattern and "|" starts a ++" new Ex command, so the field runs as an Ex command during completion. ++func Test_ccomplete_no_exec_via_typeref() ++ unlet! g:ccomplete_injected ++ let tagsfile = s:WriteTags([ ++ \ "myvar\tmain.c\t/^x$/;\"\tv\ttyperef:x/|let g:ccomplete_injected = 1|\"", ++ \ ]) ++ ++ let save_tags = &tags ++ let &tags = tagsfile ++ ++ new ++ call ccomplete#Complete(1, '') ++ call ccomplete#Complete(0, 'myvar.x') ++ ++ call assert_false(exists('g:ccomplete_injected'), ++ \ 'typeref field was executed as an Ex command during omni-completion') ++ ++ bwipe! ++ let &tags = save_tags ++ unlet! g:ccomplete_injected ++endfunc ++ ++" A legitimate typeref must still drive struct-member completion: escaping the ++" field value must not break the normal path. ++func Test_ccomplete_typeref_completion_still_works() ++ let tagsfile = s:WriteTags([ ++ \ "myvar\tmain.c\t/^x$/;\"\tv\ttyperef:struct:mystruct", ++ \ "alpha\tmain.c\t/^x$/;\"\tm\tstruct:mystruct", ++ \ "beta\tmain.c\t/^x$/;\"\tm\tstruct:mystruct", ++ \ ]) ++ ++ let save_tags = &tags ++ let &tags = tagsfile ++ ++ new ++ call ccomplete#Complete(1, '') ++ let items = ccomplete#Complete(0, 'myvar.') ++ ++ call assert_equal(type([]), type(items), ++ \ 'ccomplete#Complete did not return a list') ++ let names = map(copy(items), 'v:val.word') ++ call assert_true(index(names, 'alpha') >= 0, ++ \ 'struct member "alpha" missing from completion: ' . string(names)) ++ call assert_true(index(names, 'beta') >= 0, ++ \ 'struct member "beta" missing from completion: ' . string(names)) ++ ++ bwipe! ++ let &tags = save_tags ++endfunc ++ ++" vim: shiftwidth=2 sts=2 expandtab diff --git a/0001-runtime-ccomplete-fix-type-mismatch-error.patch b/0001-runtime-ccomplete-fix-type-mismatch-error.patch new file mode 100644 index 00000000..b76b9c5a --- /dev/null +++ b/0001-runtime-ccomplete-fix-type-mismatch-error.patch @@ -0,0 +1,30 @@ +From d9ec67691170cd3764cbf767636305e47987340f Mon Sep 17 00:00:00 2001 +From: "Lars T. Kyllingstad" +Date: Thu, 6 Jun 2024 18:37:08 +0200 +Subject: [PATCH] runtime(ccomplete): fix type mismatch error + +fixes: #14927 +closes: #14928 + +Signed-off-by: Lars T. Kyllingstad +Signed-off-by: Christian Brabandt +--- + runtime/autoload/ccomplete.vim | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/runtime/autoload/ccomplete.vim b/runtime/autoload/ccomplete.vim +index 7096dcf4a..355f724d0 100644 +--- a/runtime/autoload/ccomplete.vim ++++ b/runtime/autoload/ccomplete.vim +@@ -210,7 +210,7 @@ export def Complete(findstart: bool, abase: string): any # {{{1 + # Find the variable in the tags file(s) + var diclist: list> = taglist('^' .. items[0] .. '$') + # Remove members, these can't appear without something in front. +- ->filter((_, v: dict): bool => ++ ->filter((_, v: dict): bool => + v->has_key('kind') ? v.kind != 'm' : true) + + res = [] +-- +2.55.0 + diff --git a/vim.spec b/vim.spec index 2b2b2db1..38d928e0 100644 --- a/vim.spec +++ b/vim.spec @@ -51,7 +51,7 @@ Summary: The VIM editor URL: http://www.vim.org/ Name: vim Version: %{baseversion}.%{patchlevel} -Release: 17%{?dist} +Release: 18%{?dist} Epoch: 2 # swift.vim contains Apache 2.0 with runtime library exception: # which is taken as Apache-2.0 WITH Swift-exception - reported to legal as https://gitlab.com/fedora/legal/fedora-license-data/-/issues/188 @@ -167,6 +167,12 @@ Patch3025: 0001-patch-9.2.0736-potential-command-execution-in-PHP-om.patch # https://redhat.atlassian.net/browse/RHEL-191361 # https://github.com/vim/vim/commit/497f931f85339d175d7f69588dd249e8ccfed41b Patch3026: 0001-patch-9.2.0698-security-Out-of-bounds-write-with-sou.patch +# RHEL-203886 CVE-2026-59858 vim: arbitrary Ex command execution during C omni-completion +# https://redhat.atlassian.net/browse/RHEL-203886 +# https://github.com/vim/vim/commit/6b611b0d15603c52ebdad17172b0232b4f65704e +# https://github.com/vim/vim/commit/d9ec67691170cd3764cbf767636305e47987340f +Patch3027: 0001-patch-9.2.0735-security-arbitrary-Ex-command-executi.patch +Patch3028: 0001-runtime-ccomplete-fix-type-mismatch-error.patch # uses autoconf in spec file @@ -511,6 +517,8 @@ perl -pi -e "s,bin/nawk,bin/awk,g" runtime/tools/mve.awk %patch -P 3024 -p1 -b .cucumber-code-inject %patch -P 3025 -p1 -b .php-omni-cmd-exec %patch -P 3026 -p1 -b .soundfold-overflow +%patch -P 3027 -p1 -b .ccomplete-ex-inject +%patch -P 3028 -p1 -b .runtime-ccomplete %build cd src @@ -1141,6 +1149,10 @@ touch %{buildroot}/%{_datadir}/%{name}/vimfiles/doc/tags %changelog +* Wed Jul 29 2026 RHEL Packaging Agent - 2:9.1.083-18 +- RHEL-203886 CVE-2026-59858 vim: arbitrary Ex command execution in C + omni-completion + * Wed Jul 29 2026 RHEL Packaging Agent - 2:9.1.083-17 - RHEL-191361 CVE-2026-57455 vim: Out-of-bounds write with soundfold()