From 68baf96826dbc9a119a8054090434077620c9955 Mon Sep 17 00:00:00 2001 From: AlmaLinux RelEng Bot Date: Mon, 30 Mar 2026 10:04:40 -0400 Subject: [PATCH] import CS vim-8.2.2637-26.el9 --- ...rash-when-recovering-from-corrupted-.patch | 108 +++++ ...ecurity-path-traversal-issue-in-zip..patch | 70 +++ ...ecurity-path-traversal-issue-in-tar..patch | 327 +++++++++++++ ...ecurity-buffer-overflow-in-helpfile-.patch | 42 ++ ...nother-case-of-buffer-overflow-with-.patch | 52 ++ ...ecurity-possible-command-injection-u.patch | 56 +++ ...ecurity-Crash-when-recovering-a-corr.patch | 456 ++++++++++++++++++ ...etrw-does-not-take-port-into-account.patch | 39 ++ ...time-netrw-upstream-snapshot-of-v179.patch | 65 +++ SOURCES/vi_wrapper | 23 - SOURCES/view_wrapper | 2 +- SOURCES/vim-CVE-2023-4752.patch | 262 ++++++++++ SPECS/vim.spec | 84 +++- 13 files changed, 1548 insertions(+), 38 deletions(-) create mode 100644 SOURCES/0001-patch-9.0.1477-crash-when-recovering-from-corrupted-.patch create mode 100644 SOURCES/0001-patch-9.1.1551-security-path-traversal-issue-in-zip..patch create mode 100644 SOURCES/0001-patch-9.1.1552-security-path-traversal-issue-in-tar..patch create mode 100644 SOURCES/0001-patch-9.1.2132-security-buffer-overflow-in-helpfile-.patch create mode 100644 SOURCES/0001-patch-9.1.2133-Another-case-of-buffer-overflow-with-.patch create mode 100644 SOURCES/0001-patch-9.2.0073-security-possible-command-injection-u.patch create mode 100644 SOURCES/0001-patch-9.2.0077-security-Crash-when-recovering-a-corr.patch create mode 100644 SOURCES/0001-patch-9.2.0089-netrw-does-not-take-port-into-account.patch create mode 100644 SOURCES/0001-runtime-netrw-upstream-snapshot-of-v179.patch delete mode 100644 SOURCES/vi_wrapper create mode 100644 SOURCES/vim-CVE-2023-4752.patch diff --git a/SOURCES/0001-patch-9.0.1477-crash-when-recovering-from-corrupted-.patch b/SOURCES/0001-patch-9.0.1477-crash-when-recovering-from-corrupted-.patch new file mode 100644 index 00000000..bc0fe031 --- /dev/null +++ b/SOURCES/0001-patch-9.0.1477-crash-when-recovering-from-corrupted-.patch @@ -0,0 +1,108 @@ +diff -up vim82/src/errors.h.check-page-count vim82/src/errors.h +--- vim82/src/errors.h.check-page-count 2026-03-19 17:53:51.063638067 +0100 ++++ vim82/src/errors.h 2026-03-19 17:56:16.144187736 +0100 +@@ -391,3 +391,5 @@ EXTERN char e_string_or_function_require + EXTERN char e_illegal_character_in_word[] + INIT(= N_("E1280: Illegal character in word")); + #endif ++EXTERN char e_warning_pointer_block_corrupted[] ++ INIT(= N_("E1364: Warning: Pointer block corrupted")); +diff -up vim82/src/memfile.c.check-page-count vim82/src/memfile.c +--- vim82/src/memfile.c.check-page-count 2021-03-22 10:02:42.000000000 +0100 ++++ vim82/src/memfile.c 2026-03-19 18:13:11.196323045 +0100 +@@ -432,7 +432,9 @@ mf_get(memfile_T *mfp, blocknr_T nr, int + * If not, allocate a new block. + */ + hp = mf_release(mfp, page_count); +- if (hp == NULL && (hp = mf_alloc_bhdr(mfp, page_count)) == NULL) ++ if (hp == NULL && page_count > 0) ++ hp = mf_alloc_bhdr(mfp, page_count); ++ if (hp == NULL) + return NULL; + + hp->bh_bnum = nr; +@@ -813,8 +815,10 @@ mf_release(memfile_T *mfp, int page_coun + */ + if (hp->bh_page_count != page_count) + { +- vim_free(hp->bh_data); +- if ((hp->bh_data = alloc(mfp->mf_page_size * page_count)) == NULL) ++ VIM_CLEAR(hp->bh_data); ++ if (page_count > 0) ++ hp->bh_data = alloc((size_t)mfp->mf_page_size * page_count); ++ if (hp->bh_data == NULL) + { + vim_free(hp); + return NULL; +@@ -872,7 +876,7 @@ mf_release_all(void) + } + + /* +- * Allocate a block header and a block of memory for it ++ * Allocate a block header and a block of memory for it. + */ + static bhdr_T * + mf_alloc_bhdr(memfile_T *mfp, int page_count) +@@ -892,7 +896,7 @@ mf_alloc_bhdr(memfile_T *mfp, int page_c + } + + /* +- * Free a block header and the block of memory for it ++ * Free a block header and the block of memory for it. + */ + static void + mf_free_bhdr(bhdr_T *hp) +@@ -902,7 +906,7 @@ mf_free_bhdr(bhdr_T *hp) + } + + /* +- * insert entry *hp in the free list ++ * Insert entry *hp in the free list. + */ + static void + mf_ins_free(memfile_T *mfp, bhdr_T *hp) +diff -up vim82/src/memline.c.check-page-count vim82/src/memline.c +--- vim82/src/memline.c.check-page-count 2021-03-22 10:02:42.000000000 +0100 ++++ vim82/src/memline.c 2026-03-19 18:13:59.116720443 +0100 +@@ -96,6 +96,9 @@ struct pointer_block + // followed by empty space until end of page + }; + ++// Value for pb_count_max. ++#define PB_COUNT_MAX(mfp) (short_u)(((mfp)->mf_page_size - offsetof(PTR_BL, pb_pointer)) / sizeof(PTR_EN)) ++ + /* + * A data block is a leaf in the tree. + * +@@ -1505,6 +1508,20 @@ ml_recover(int checkext) + pp = (PTR_BL *)(hp->bh_data); + if (pp->pb_id == PTR_ID) // it is a pointer block + { ++ int ptr_block_error = FALSE; ++ if (pp->pb_count_max != PB_COUNT_MAX(mfp)) ++ { ++ ptr_block_error = TRUE; ++ pp->pb_count_max = PB_COUNT_MAX(mfp); ++ } ++ if (pp->pb_count > pp->pb_count_max) ++ { ++ ptr_block_error = TRUE; ++ pp->pb_count = pp->pb_count_max; ++ } ++ if (ptr_block_error) ++ emsg(_(e_warning_pointer_block_corrupted)); ++ + // check line count when using pointer block first time + if (idx == 0 && line_count != 0) + { +@@ -4040,8 +4057,7 @@ ml_new_ptr(memfile_T *mfp) + pp = (PTR_BL *)(hp->bh_data); + pp->pb_id = PTR_ID; + pp->pb_count = 0; +- pp->pb_count_max = (short_u)((mfp->mf_page_size - sizeof(PTR_BL)) +- / sizeof(PTR_EN) + 1); ++ pp->pb_count_max = PB_COUNT_MAX(mfp); + + return hp; + } +diff -up vim82/src/testdir/test_recover.vim.check-page-count vim82/src/testdir/test_recover.vim diff --git a/SOURCES/0001-patch-9.1.1551-security-path-traversal-issue-in-zip..patch b/SOURCES/0001-patch-9.1.1551-security-path-traversal-issue-in-zip..patch new file mode 100644 index 00000000..2de1c393 --- /dev/null +++ b/SOURCES/0001-patch-9.1.1551-security-path-traversal-issue-in-zip..patch @@ -0,0 +1,70 @@ +diff -up vim82/runtime/autoload/zip.vim.CVE-2025-53906 vim82/runtime/autoload/zip.vim +--- vim82/runtime/autoload/zip.vim.CVE-2025-53906 2021-03-22 10:02:41.000000000 +0100 ++++ vim82/runtime/autoload/zip.vim 2025-09-10 19:33:11.491115978 +0200 +@@ -251,6 +251,7 @@ fun! zip#Write(fname) + " call Dfunc("zip#Write(fname<".a:fname.">) zipfile_".winnr()."<".s:zipfile_{winnr()}.">") + let repkeep= &report + set report=10 ++ let need_rename = 0 + + " sanity checks + if !executable(substitute(g:zip_zipcmd,'\s\+.*$','','')) +@@ -261,14 +262,6 @@ fun! zip#Write(fname) + " call Dret("zip#Write") + return + endif +- if !exists("*mkdir") +- redraw! +- echohl Error | echo "***error*** (zip#Write) sorry, mkdir() doesn't work on your system" | echohl None +-" call inputsave()|call input("Press to continue")|call inputrestore() +- let &report= repkeep +-" call Dret("zip#Write") +- return +- endif + + let curdir= getcwd() + let tmpdir= tempname() +@@ -302,6 +295,11 @@ fun! zip#Write(fname) + let zipfile = substitute(a:fname,'^.\{-}zipfile:\(.\{-}\)::[^\\].*$','\1','') + let fname = substitute(a:fname,'^.\{-}zipfile:.\{-}::\([^\\].*\)$','\1','') + endif ++ if fname =~ '^[.]\{1,2}/' ++ call system(g:zip_zipcmd." -d ".s:Escape(fnamemodify(zipfile,":p"),0)." ".s:Escape(fname,0)) ++ let fname = fname->substitute('^\([.]\{1,2}/\)\+', '', 'g') ++ let need_rename = 1 ++ endif + " call Decho("zipfile<".zipfile.">") + " call Decho("fname <".fname.">") + +@@ -318,7 +316,7 @@ fun! zip#Write(fname) + endif + " call Decho("zipfile<".zipfile."> fname<".fname.">") + +- exe "w! ".fnameescape(fname) ++ exe "w ".fnameescape(fname) + if has("win32unix") && executable("cygpath") + let zipfile = substitute(system("cygpath ".s:Escape(zipfile,0)),'\n','','e') + endif +@@ -348,6 +346,10 @@ fun! zip#Write(fname) + let &binary = binkeep + q! + unlet s:zipfile_{winnr()} ++ elseif need_rename ++ exe $"sil keepalt file {fnameescape($"zipfile://{zipfile}::{fname}")}" ++ redraw! ++ echohl Error | echo "***error*** (zip#Browse) Path Traversal Attack detected, dropping relative path" | echohl None + endif + + " cleanup and restore current directory +@@ -383,6 +385,11 @@ fun! zip#Extract() + let &report= repkeep + " call Dret("zip#Extract") + return ++ elseif fname =~ '^[.]\?[.]/' ++ redraw! ++ echohl Error | echo "***error*** (zip#Browse) Path Traversal Attack detected, not extracting!" | echohl None ++ let &report= repkeep ++ return + endif + + " extract the file mentioned under the cursor diff --git a/SOURCES/0001-patch-9.1.1552-security-path-traversal-issue-in-tar..patch b/SOURCES/0001-patch-9.1.1552-security-path-traversal-issue-in-tar..patch new file mode 100644 index 00000000..1fea077f --- /dev/null +++ b/SOURCES/0001-patch-9.1.1552-security-path-traversal-issue-in-tar..patch @@ -0,0 +1,327 @@ +diff -up vim82/runtime/autoload/tar.vim.CVE-2025-53905 vim82/runtime/autoload/tar.vim +--- vim82/runtime/autoload/tar.vim.CVE-2025-53905 2021-03-22 10:02:41.000000000 +0100 ++++ vim82/runtime/autoload/tar.vim 2025-09-10 19:28:55.467111778 +0200 +@@ -37,10 +37,10 @@ set cpo&vim + " --------------------------------------------------------------------- + " Default Settings: {{{1 + if !exists("g:tar_browseoptions") +- let g:tar_browseoptions= "Ptf" ++ let g:tar_browseoptions= "tf" + endif + if !exists("g:tar_readoptions") +- let g:tar_readoptions= "OPxf" ++ let g:tar_readoptions= "Oxf" + endif + if !exists("g:tar_cmd") + let g:tar_cmd= "tar" +@@ -49,6 +49,7 @@ if !exists("g:tar_writeoptions") + let g:tar_writeoptions= "uf" + endif + if !exists("g:tar_delfile") ++ " Note: not supported on BSD + let g:tar_delfile="--delete -f" + endif + if !exists("g:netrw_cygwin") +@@ -98,6 +99,9 @@ if !exists("g:tar_shq") + " call Decho("g:tar_shq<".g:tar_shq.">") + endif + ++let g:tar_secure=' -- ' ++let g:tar_leading_pat='^\%([.]\{,2\}/\)\+' ++ + " ---------------- + " Functions: {{{1 + " ---------------- +@@ -221,6 +225,15 @@ fun! tar#Browse(tarfile) + return + endif + ++ " remove tar: Removing leading '/' from member names ++ " Note: the message could be localized ++ if search('^tar: ') > 0 || search(g:tar_leading_pat) > 0 ++ call append(3,'" Note: Path Traversal Attack detected!') ++ let b:leading_slash = 1 ++ " remove the message output ++ sil g/^tar: /d ++ endif ++ + " set up maps supported for tar + setlocal noma nomod ro + noremap :call TarBrowseSelect() +@@ -242,12 +255,7 @@ fun! s:TarBrowseSelect() + let fname= getline(".") + " call Decho("fname<".fname.">") + +- if !exists("g:tar_secure") && fname =~ '^\s*-\|\s\+-' +- redraw! +- echohl WarningMsg | echo '***warning*** (tar#BrowseSelect) rejecting tarfile member<'.fname.'> because of embedded "-"' +-" call Dret('tar#BrowseSelect : rejecting tarfile member<'.fname.'> because of embedded "-"') +- return +- endif ++ let ls= get(b:, 'leading_slash', 0) + + " sanity check + if fname =~ '^"' +@@ -270,7 +278,8 @@ fun! s:TarBrowseSelect() + wincmd _ + endif + let s:tblfile_{winnr()}= curfile +- call tar#Read("tarfile:".tarfile.'::'.fname,1) ++ let b:leading_slash= ls ++ call tar#Read("tarfile:".tarfile.'::'.fname) + filetype detect + set nomod + exe 'com! -buffer -nargs=? -complete=file TarDiff :call tar#Diff(,"'.fnameescape(fname).'")' +@@ -281,8 +290,8 @@ endfun + + " --------------------------------------------------------------------- + " tar#Read: {{{2 +-fun! tar#Read(fname,mode) +-" call Dfunc("tar#Read(fname<".a:fname.">,mode=".a:mode.")") ++fun! tar#Read(fname) ++" call Dfunc("tar#Read(fname<".a:fname.">)") + let repkeep= &report + set report=10 + let tarfile = substitute(a:fname,'tarfile:\(.\{-}\)::.*$','\1','') +@@ -294,6 +303,8 @@ fun! tar#Read(fname,mode) + " call Decho("tarfile<".tarfile.">") + " call Decho("fname<".fname.">") + ++ let curdir= getcwd() ++ let b:curdir= curdir + if fname =~ '\.bz2$' && executable("bzcat") + let decmp= "|bzcat" + let doro = 1 +@@ -317,16 +328,11 @@ fun! tar#Read(fname,mode) + endif + endif + +- if exists("g:tar_secure") +- let tar_secure= " -- " +- else +- let tar_secure= " " +- endif + + if tarfile =~# '\.bz2$' +- exe "sil! r! bzip2 -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp ++ exe "sil! r! bzip2 -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".g:tar_secure.shellescape(fname,1).decmp + elseif tarfile =~# '\.\(gz\)$' +- exe "sil! r! gzip -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp ++ exe "sil! r! gzip -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".g:tar_secure.shellescape(fname,1).decmp + + elseif tarfile =~# '\(\.tgz\|\.tbz\|\.txz\)' + if has("unix") && executable("file") +@@ -335,28 +341,31 @@ fun! tar#Read(fname,mode) + let filekind= "" + endif + if filekind =~ "bzip2" +- exe "sil! r! bzip2 -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp ++ exe "sil! r! bzip2 -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".g:tar_secure.shellescape(fname,1).decmp + elseif filekind =~ "XZ" +- exe "sil! r! xz -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp ++ exe "sil! r! xz -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".g:tar_secure.shellescape(fname,1).decmp + elseif filekind =~ "Zstandard" +- exe "sil! r! zstd --decompress --stdout -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp ++ exe "sil! r! zstd --decompress --stdout -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".g:tar_secure.shellescape(fname,1).decmp + else +- exe "sil! r! gzip -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp ++ exe "sil! r! gzip -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".g:tar_secure.shellescape(fname,1).decmp + endif + + elseif tarfile =~# '\.lrp$' +- exe "sil! r! cat -- ".shellescape(tarfile,1)." | gzip -d -c - | ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp ++ exe "sil! r! cat -- ".shellescape(tarfile,1)." | gzip -d -c - | ".g:tar_cmd." -".g:tar_readoptions." - ".g:tar_secure.shellescape(fname,1).decmp + elseif tarfile =~# '\.lzma$' +- exe "sil! r! lzma -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp ++ exe "sil! r! lzma -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".g:tar_secure.shellescape(fname,1).decmp + elseif tarfile =~# '\.\(xz\|txz\)$' +- exe "sil! r! xz --decompress --stdout -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp ++ exe "sil! r! xz --decompress --stdout -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_readoptions." - ".g:tar_secure.shellescape(fname,1).decmp + else + if tarfile =~ '^\s*-' + " A file name starting with a dash is taken as an option. Prepend ./ to avoid that. + let tarfile = substitute(tarfile, '-', './-', '') + endif +-" call Decho("8: exe silent r! ".g:tar_cmd." -".g:tar_readoptions.tar_secure.shellescape(tarfile,1)." ".shellescape(fname,1).decmp) +- exe "silent r! ".g:tar_cmd." -".g:tar_readoptions.shellescape(tarfile,1)." ".tar_secure.shellescape(fname,1).decmp ++" call Decho("8: exe silent r! ".g:tar_cmd." -".g:tar_readoptions.g:tar_secure.shellescape(tarfile,1)." ".shellescape(fname,1).decmp) ++ exe "silent r! ".g:tar_cmd." -".g:tar_readoptions.shellescape(tarfile,1)." ".g:tar_secure.shellescape(fname,1).decmp ++ endif ++ if get(b:, 'leading_slash', 0) ++ sil g/^tar: /d + endif + + if doro +@@ -365,13 +374,14 @@ fun! tar#Read(fname,mode) + endif + + let b:tarfile= a:fname +- exe "file tarfile::".fnameescape(fname) + + " cleanup + keepj sil! 0d + set nomod + + let &report= repkeep ++ exe "lcd ".fnameescape(curdir) ++ silent exe "file tarfile::". fname->fnameescape() + " call Dret("tar#Read : b:tarfile<".b:tarfile.">") + endfun + +@@ -382,13 +392,6 @@ fun! tar#Write(fname) + let repkeep= &report + set report=10 + +- if !exists("g:tar_secure") && a:fname =~ '^\s*-\|\s\+-' +- redraw! +- echohl WarningMsg | echo '***warning*** (tar#Write) rejecting tarfile member<'.a:fname.'> because of embedded "-"' +-" call Dret('tar#Write : rejecting tarfile member<'.fname.'> because of embedded "-"') +- return +- endif +- + " sanity checks + if !executable(g:tar_cmd) + redraw! +@@ -439,6 +442,13 @@ fun! tar#Write(fname) + let tarfile = substitute(b:tarfile,'tarfile:\(.\{-}\)::.*$','\1','') + let fname = substitute(b:tarfile,'tarfile:.\{-}::\(.*\)$','\1','') + ++ if get(b:, 'leading_slash', 0) ++ redraw! ++ echohl Error | echo "***error*** (tar#Write) sorry, not attempting to update ".tarfile." with ".fname | echohl None ++ let &report= repkeep ++ return ++ endif ++ + " handle compressed archives + if tarfile =~# '\.bz2' + call system("bzip2 -d -- ".shellescape(tarfile,0)) +@@ -497,19 +507,15 @@ fun! tar#Write(fname) + endif + " call Decho("tarfile<".tarfile."> fname<".fname.">") + +- if exists("g:tar_secure") +- let tar_secure= " -- " +- else +- let tar_secure= " " +- endif +- exe "w! ".fnameescape(fname) ++ " don't overwrite a file forcefully ++ exe "w ".fnameescape(fname) + if has("win32unix") && executable("cygpath") + let tarfile = substitute(system("cygpath ".shellescape(tarfile,0)),'\n','','e') + endif + + " delete old file from tarfile + " call Decho("system(".g:tar_cmd." ".g:tar_delfile." ".shellescape(tarfile,0)." -- ".shellescape(fname,0).")") +- call system(g:tar_cmd." ".g:tar_delfile." ".shellescape(tarfile,0).tar_secure.shellescape(fname,0)) ++ call system(g:tar_cmd." ".g:tar_delfile." ".shellescape(tarfile,0).g:tar_secure.shellescape(fname,0)) + if v:shell_error != 0 + redraw! + " call Decho("***error*** (tar#Write) sorry, unable to update ".fnameescape(tarfile)." with ".fnameescape(fname)) +@@ -517,8 +523,8 @@ fun! tar#Write(fname) + else + + " update tarfile with new file +-" call Decho(g:tar_cmd." -".g:tar_writeoptions." ".shellescape(tarfile,0).tar_secure.shellescape(fname,0)) +- call system(g:tar_cmd." -".g:tar_writeoptions." ".shellescape(tarfile,0).tar_secure.shellescape(fname,0)) ++" call Decho(g:tar_cmd." -".g:tar_writeoptions." ".shellescape(tarfile,0).g:tar_secure.shellescape(fname,0)) ++ call system(g:tar_cmd." -".g:tar_writeoptions." ".shellescape(tarfile,0).g:tar_secure.shellescape(fname,0)) + if v:shell_error != 0 + redraw! + " call Decho("***error*** (tar#Write) sorry, unable to update ".fnameescape(tarfile)." with ".fnameescape(fname)) +@@ -568,6 +574,7 @@ fun! tar#Diff(userfname,fname) + if a:userfname != "" + let fname= a:userfname + endif ++ exe "lcd ".fnameescape(b:tmpdir). '/_ZIPVIM_' + if filereadable(fname) + " sets current file (from tarball) for diff'ing + " splits window vertically +@@ -594,13 +601,6 @@ fun! tar#Extract() + let fname= getline(".") + " call Decho("fname<".fname.">") + +- if !exists("g:tar_secure") && fname =~ '^\s*-\|\s\+-' +- redraw! +- echohl WarningMsg | echo '***warning*** (tar#BrowseSelect) rejecting tarfile member<'.fname.'> because of embedded "-"' +-" call Dret('tar#BrowseSelect : rejecting tarfile member<'.fname.'> because of embedded "-"') +- return +- endif +- + " sanity check + if fname =~ '^"' + let &report= repkeep +@@ -621,7 +621,7 @@ fun! tar#Extract() + echohl Error | echo "***error*** ".extractcmd." ".tarbase.".tar ".fname.": failed!" | echohl NONE + " call Decho("***error*** ".extractcmd." ".tarbase.".tar ".fname.": failed!") + else +- echo "***note*** successfully extracted ".fname ++ echo "***note*** successfully extracted ". fname + endif + + elseif filereadable(tarbase.".tgz") +diff -up vim82/runtime/doc/pi_tar.txt.CVE-2025-53905 vim82/runtime/doc/pi_tar.txt +--- vim82/runtime/doc/pi_tar.txt.CVE-2025-53905 2021-03-22 10:02:41.000000000 +0100 ++++ vim82/runtime/doc/pi_tar.txt 2025-09-10 19:30:36.070085946 +0200 +@@ -61,7 +61,7 @@ Copyright 2005-2017: *tar-copyright* + the file mentioned in the tarball. If the current directory is not + correct for that path, :TarDiff will fail to find the associated file. + +- If the [filename] is given, that that filename (and path) will be used ++ If the [filename] is given, that filename (and path) will be used + to specify the associated file. + + +@@ -86,18 +86,6 @@ Copyright 2005-2017: *tar-copyright* + *g:tar_readoptions* "OPxf" used to extract a file from a tarball + *g:tar_cmd* "tar" the name of the tar program + *g:tar_nomax* 0 if true, file window will not be maximized +- *g:tar_secure* undef if exists: +- "--"s will be used to prevent unwanted +- option expansion in tar commands. +- Please be sure that your tar command +- accepts "--"; Posix compliant tar +- utilities do accept them. +- if not exists: +- The tar plugin will reject any tar +- files or member files that begin with +- "-" +- Not all tar's support the "--" which is why +- it isn't default. + *g:tar_writeoptions* "uf" used to update/replace a file + + +diff -up vim82/runtime/doc/tags.CVE-2025-53905 vim82/runtime/doc/tags +--- vim82/runtime/doc/tags.CVE-2025-53905 2021-03-22 10:02:41.000000000 +0100 ++++ vim82/runtime/doc/tags 2025-09-10 19:31:03.339666639 +0200 +@@ -6900,7 +6900,6 @@ g:tar_copycmd pi_tar.txt /*g:tar_copycmd + g:tar_extractcmd pi_tar.txt /*g:tar_extractcmd* + g:tar_nomax pi_tar.txt /*g:tar_nomax* + g:tar_readoptions pi_tar.txt /*g:tar_readoptions* +-g:tar_secure pi_tar.txt /*g:tar_secure* + g:tar_writeoptions pi_tar.txt /*g:tar_writeoptions* + g:terminal_ansi_colors terminal.txt /*g:terminal_ansi_colors* + g:tex_comment_nospell syntax.txt /*g:tex_comment_nospell* +diff -up vim82/runtime/plugin/tarPlugin.vim.CVE-2025-53905 vim82/runtime/plugin/tarPlugin.vim +--- vim82/runtime/plugin/tarPlugin.vim.CVE-2025-53905 2021-03-22 10:02:42.000000000 +0100 ++++ vim82/runtime/plugin/tarPlugin.vim 2025-09-10 19:25:22.726912254 +0200 +@@ -22,14 +22,14 @@ set cpo&vim + " Public Interface: {{{1 + augroup tar + au! +- au BufReadCmd tarfile::* call tar#Read(expand(""), 1) +- au FileReadCmd tarfile::* call tar#Read(expand(""), 0) ++ au BufReadCmd tarfile::* call tar#Read(expand("")) ++ au FileReadCmd tarfile::* call tar#Read(expand("")) + au BufWriteCmd tarfile::* call tar#Write(expand("")) + au FileWriteCmd tarfile::* call tar#Write(expand("")) + + if has("unix") +- au BufReadCmd tarfile::*/* call tar#Read(expand(""), 1) +- au FileReadCmd tarfile::*/* call tar#Read(expand(""), 0) ++ au BufReadCmd tarfile::*/* call tar#Read(expand("")) ++ au FileReadCmd tarfile::*/* call tar#Read(expand("")) + au BufWriteCmd tarfile::*/* call tar#Write(expand("")) + au FileWriteCmd tarfile::*/* call tar#Write(expand("")) + endif diff --git a/SOURCES/0001-patch-9.1.2132-security-buffer-overflow-in-helpfile-.patch b/SOURCES/0001-patch-9.1.2132-security-buffer-overflow-in-helpfile-.patch new file mode 100644 index 00000000..29dd29e2 --- /dev/null +++ b/SOURCES/0001-patch-9.1.2132-security-buffer-overflow-in-helpfile-.patch @@ -0,0 +1,42 @@ +diff --git a/src/structs.h b/src/structs.h +index 75ad127..d6763ab 100644 +--- a/src/structs.h ++++ b/src/structs.h +@@ -4422,3 +4422,6 @@ typedef struct { + char wt_variable; // "variable" when TRUE, "argument" otherwise + } where_T; + ++// Return the length of a string literal ++#define STRLEN_LITERAL(s) (sizeof(s) - 1) ++ +diff --git a/src/tag.c b/src/tag.c +index 37ed66c..c305f25 100644 +--- a/src/tag.c ++++ b/src/tag.c +@@ -2912,7 +2912,7 @@ get_tagfname( + if (tnp->tn_hf_idx > tag_fnames.ga_len || *p_hf == NUL) + return FAIL; + ++tnp->tn_hf_idx; +- STRCPY(buf, p_hf); ++ vim_strncpy(buf, p_hf, MAXPATHL - 1); + STRCPY(gettail(buf), "tags"); + #ifdef BACKSLASH_IN_FILENAME + slash_adjust(buf); +diff --git a/src/testdir/test_help.vim b/src/testdir/test_help.vim +index c8ff5b8..6a45194 100644 +--- a/src/testdir/test_help.vim ++++ b/src/testdir/test_help.vim +@@ -131,5 +131,13 @@ func Test_help_long_argument() + endtry + endfunc + ++" This caused a buffer overflow ++func Test_helpfile_overflow() ++ let _helpfile = &helpfile ++ let &helpfile = repeat('A', 5000) ++ help ++ helpclose ++ let &helpfile = _helpfile ++endfunc + + " vim: shiftwidth=2 sts=2 expandtab diff --git a/SOURCES/0001-patch-9.1.2133-Another-case-of-buffer-overflow-with-.patch b/SOURCES/0001-patch-9.1.2133-Another-case-of-buffer-overflow-with-.patch new file mode 100644 index 00000000..4a4be5b9 --- /dev/null +++ b/SOURCES/0001-patch-9.1.2133-Another-case-of-buffer-overflow-with-.patch @@ -0,0 +1,52 @@ +From 21d591fb12b08b52d92253bf9ac4b866475d62d6 Mon Sep 17 00:00:00 2001 +From: zeertzjq +Date: Fri, 6 Feb 2026 09:37:58 +0000 +Subject: [PATCH] patch 9.1.2133: Another case of buffer overflow with + 'helpfile' + +Problem: Another case of buffer overflow with 'helpfile'. +Solution: Leave room for "tags" in the buffer (zeertzjq). + +closes: #19340 + +Signed-off-by: zeertzjq +Signed-off-by: Christian Brabandt +--- + runtime/doc/version9.txt | 6 +++++- + src/tag.c | 2 +- + src/testdir/test_help.vim | 5 +++++ + src/version.c | 2 ++ + 4 files changed, 13 insertions(+), 2 deletions(-) + +diff --git a/src/tag.c b/src/tag.c +index 78e7c80a1..6968aac27 100644 +--- a/src/tag.c ++++ b/src/tag.c +@@ -3347,7 +3347,7 @@ get_tagfname( + if (tnp->tn_hf_idx > tag_fnames.ga_len || *p_hf == NUL) + return FAIL; + ++tnp->tn_hf_idx; +- vim_strncpy(buf, p_hf, MAXPATHL - 1); ++ vim_strncpy(buf, p_hf, MAXPATHL - STRLEN_LITERAL("tags") - 1); + STRCPY(gettail(buf), "tags"); + #ifdef BACKSLASH_IN_FILENAME + slash_adjust(buf); +diff --git a/src/testdir/test_help.vim b/src/testdir/test_help.vim +index d30ef17b0..1a52998f9 100644 +--- a/src/testdir/test_help.vim ++++ b/src/testdir/test_help.vim +@@ -281,6 +281,11 @@ func Test_helpfile_overflow() + let &helpfile = repeat('A', 5000) + help + helpclose ++ for i in range(4089, 4096) ++ let &helpfile = repeat('A', i) .. '/A' ++ help ++ helpclose ++ endfor + let &helpfile = _helpfile + endfunc + +-- +2.53.0 + diff --git a/SOURCES/0001-patch-9.2.0073-security-possible-command-injection-u.patch b/SOURCES/0001-patch-9.2.0073-security-possible-command-injection-u.patch new file mode 100644 index 00000000..962ee487 --- /dev/null +++ b/SOURCES/0001-patch-9.2.0073-security-possible-command-injection-u.patch @@ -0,0 +1,56 @@ +diff -up vim91/runtime/autoload/netrw.vim.CVE-2026-28417 vim91/runtime/autoload/netrw.vim +--- vim91/runtime/autoload/netrw.vim.CVE-2026-28417 2026-03-17 19:22:17.101915588 +0100 ++++ vim91/runtime/autoload/netrw.vim 2026-03-17 19:32:29.134514079 +0100 +@@ -3376,13 +3376,26 @@ endif + + " s:NetrwValidateHostname: Validate that the hostname is valid {{{2 + " Input: +-" hostname ++" hostname, may include an optional username, e.g. user@hostname ++" allow a alphanumeric hostname or an IPv(4/6) address + " Output: + " true if g:netrw_machine is valid according to RFC1123 #Section 2 + fun! s:NetrwValidateHostname(hostname) +- " RFC1123#section-2 mandates, a valid hostname starts with letters or digits +- " so reject everyhing else +- return a:hostname =~? '^[a-z0-9]' ++ " Username: ++ let user_pat = '\%([a-zA-Z0-9._-]\+@\)\?' ++ " Hostname: 1-64 chars, alphanumeric/dots/hyphens. ++ " No underscores. No leading/trailing dots/hyphens. ++ let host_pat = '[a-zA-Z0-9]\%([-a-zA-Z0-9.]{,62}[a-zA-Z0-9]\)\?$' ++ ++ " IPv4: 1-3 digits separated by dots ++ let ipv4_pat = '\%(\d\{1,3}\.\)\{3\}\d\{1,3\}$' ++ ++ " IPv6: Hex, colons, and optional brackets ++ let ipv6_pat = '\[\?\%([a-fA-F0-9:]\{2,}\)\+\]\?$' ++ ++ return a:hostname =~? '^'.user_pat.host_pat || ++ \ a:hostname =~? '^'.user_pat.ipv4_pat || ++ \ a:hostname =~? '^'.user_pat.ipv6_pat + endfun + + " --------------------------------------------------------------------- +@@ -11880,15 +11893,15 @@ endfun + " a correct command for use with a system() call + fun! s:MakeSshCmd(sshcmd) + " call Dfunc("s:MakeSshCmd(sshcmd<".a:sshcmd.">) user<".s:user."> machine<".s:machine.">") +- if s:user == "" +- let sshcmd = substitute(a:sshcmd,'\',s:machine,'') +- else +- let sshcmd = substitute(a:sshcmd,'\',s:user."@".s:machine,'') ++ let machine = shellescape(s:machine, 1) ++ if s:user != '' ++ let machine = shellescape(s:user, 1).'@'.machine + endif ++ let sshcmd = substitute(a:sshcmd,'\',machine,'') + if exists("g:netrw_port") && g:netrw_port != "" +- let sshcmd= substitute(sshcmd,"USEPORT",g:netrw_sshport.' '.g:netrw_port,'') ++ let sshcmd= substitute(sshcmd,"USEPORT",g:netrw_sshport.' '.shellescape(g:netrw_port,1),'') + elseif exists("s:port") && s:port != "" +- let sshcmd= substitute(sshcmd,"USEPORT",g:netrw_sshport.' '.s:port,'') ++ let sshcmd= substitute(sshcmd,"USEPORT",g:netrw_sshport.' '.shellescape(s:port,1),'') + else + let sshcmd= substitute(sshcmd,"USEPORT ",'','') + endif diff --git a/SOURCES/0001-patch-9.2.0077-security-Crash-when-recovering-a-corr.patch b/SOURCES/0001-patch-9.2.0077-security-Crash-when-recovering-a-corr.patch new file mode 100644 index 00000000..d7262c2a --- /dev/null +++ b/SOURCES/0001-patch-9.2.0077-security-Crash-when-recovering-a-corr.patch @@ -0,0 +1,456 @@ +diff -up vim82/src/memline.c.CVE-2026-28421 vim82/src/memline.c +--- vim82/src/memline.c.CVE-2026-28421 2021-03-22 10:02:42.000000000 +0100 ++++ vim82/src/memline.c 2026-03-19 10:42:50.113672743 +0100 +@@ -1536,8 +1536,12 @@ ml_recover(int checkext) + if (!cannot_open) + { + line_count = pp->pb_pointer[idx].pe_line_count; +- if (readfile(curbuf->b_ffname, NULL, lnum, +- pp->pb_pointer[idx].pe_old_lnum - 1, ++ linenr_T pe_old_lnum = pp->pb_pointer[idx].pe_old_lnum; ++ // Validate pe_line_count and pe_old_lnum from the ++ // untrusted swap file before passing to readfile(). ++ if (line_count <= 0 || pe_old_lnum < 1 || ++ readfile(curbuf->b_ffname, NULL, lnum, ++ pe_old_lnum - 1, + line_count, NULL, 0) != OK) + cannot_open = TRUE; + else +@@ -1568,6 +1572,27 @@ ml_recover(int checkext) + bnum = pp->pb_pointer[idx].pe_bnum; + line_count = pp->pb_pointer[idx].pe_line_count; + page_count = pp->pb_pointer[idx].pe_page_count; ++ // Validate pe_bnum and pe_page_count from the untrusted ++ // swap file before passing to mf_get(), which uses ++ // page_count to calculate allocation size. A bogus value ++ // (e.g. 0x40000000) would cause a multi-GB allocation. ++ // pe_page_count must be >= 1 and bnum + page_count must ++ // not exceed the number of pages in the swap file. ++ if (page_count < 1 ++ || bnum + page_count > mfp->mf_blocknr_max + 1) ++ { ++ ++error; ++ ml_append(lnum++, ++ (char_u *)_("???ILLEGAL BLOCK NUMBER"), ++ (colnr_T)0, TRUE); ++ // Skip this entry and pop back up the stack to keep ++ // recovering whatever else we can. ++ idx = ip->ip_index + 1; ++ bnum = ip->ip_bnum; ++ page_count = 1; ++ --buf->b_ml.ml_stack_top; ++ continue; ++ } + idx = 0; + continue; + } +diff -up vim82/src/po/af.po.CVE-2026-28421 vim82/src/po/af.po +--- vim82/src/po/af.po.CVE-2026-28421 2021-03-22 10:02:42.000000000 +0100 ++++ vim82/src/po/af.po 2026-03-19 10:52:18.095330396 +0100 +@@ -5342,3 +5342,6 @@ msgstr "E463: Omgewing is onder bewaking + + #~ msgid "WARNING: tag command changed a buffer!!!" + #~ msgstr "WAARSKUWING: etiketbevel het buffer verander!!!" ++ ++msgid "???ILLEGAL BLOCK NUMBER" ++msgstr "" +diff -up vim82/src/po/ca.po.CVE-2026-28421 vim82/src/po/ca.po +--- vim82/src/po/ca.po.CVE-2026-28421 2021-03-22 10:02:42.000000000 +0100 ++++ vim82/src/po/ca.po 2026-03-19 10:52:18.095330396 +0100 +@@ -6928,3 +6928,6 @@ msgid "" + msgstr "" + "Error en establir el path: sys.path no s una llista\n" + "Haureu d'afegir vim.VIM_SPECIAL_PATH a sys.path" ++ ++msgid "???ILLEGAL BLOCK NUMBER" ++msgstr "" +diff -up vim82/src/po/cs.cp1250.po.CVE-2026-28421 vim82/src/po/cs.cp1250.po +--- vim82/src/po/cs.cp1250.po.CVE-2026-28421 2021-03-22 10:02:43.000000000 +0100 ++++ vim82/src/po/cs.cp1250.po 2026-03-19 10:42:50.114884754 +0100 +@@ -4620,3 +4620,6 @@ msgstr "Nulov poet" + + msgid "E81: Using not in a script context" + msgstr "E81: Pouit mimo kontext skriptu" ++ ++msgid "???ILLEGAL BLOCK NUMBER" ++msgstr "" +diff -up vim82/src/po/cs.po.CVE-2026-28421 vim82/src/po/cs.po +--- vim82/src/po/cs.po.CVE-2026-28421 2021-03-22 10:02:42.000000000 +0100 ++++ vim82/src/po/cs.po 2026-03-19 10:42:50.115102712 +0100 +@@ -4620,3 +4620,6 @@ msgstr "Nulov poet" + + msgid "E81: Using not in a script context" + msgstr "E81: Pouit mimo kontext skriptu" ++ ++msgid "???ILLEGAL BLOCK NUMBER" ++msgstr "" +diff -up vim82/src/po/da.po.CVE-2026-28421 vim82/src/po/da.po +--- vim82/src/po/da.po.CVE-2026-28421 2021-03-22 10:02:42.000000000 +0100 ++++ vim82/src/po/da.po 2026-03-19 10:42:50.115354083 +0100 +@@ -7090,3 +7090,6 @@ msgstr "" + "C-kildekode (*.c, *.h)\t*.c;*.h\n" + "C++-kildekode (*.cpp, *.hpp)\t*.cpp;*.hpp\n" + "Vim-filer (*.vim, _vimrc, _gvimrc)\t*.vim;_vimrc;_gvimrc\n" ++ ++msgid "???ILLEGAL BLOCK NUMBER" ++msgstr "" +diff -up vim82/src/po/de.po.CVE-2026-28421 vim82/src/po/de.po +--- vim82/src/po/de.po.CVE-2026-28421 2021-03-22 10:02:42.000000000 +0100 ++++ vim82/src/po/de.po 2026-03-19 10:52:18.095330396 +0100 +@@ -9491,3 +9491,6 @@ msgstr "Name der dynamischen MzScheme Bi + + msgid "name of the MzScheme GC dynamic library" + msgstr "Name der dynamischen MzScheme GC Bibliothek" ++ ++msgid "???ILLEGAL BLOCK NUMBER" ++msgstr "" +diff -up vim82/src/po/en_GB.po.CVE-2026-28421 vim82/src/po/en_GB.po +--- vim82/src/po/en_GB.po.CVE-2026-28421 2021-03-22 10:02:42.000000000 +0100 ++++ vim82/src/po/en_GB.po 2026-03-19 10:52:18.095330396 +0100 +@@ -763,3 +763,6 @@ msgid "can't delete OutputObject attribu + msgstr "cannot delete OutputObject attributes" + + ++ ++msgid "???ILLEGAL BLOCK NUMBER" ++msgstr "" +diff -up vim82/src/po/eo.po.CVE-2026-28421 vim82/src/po/eo.po +--- vim82/src/po/eo.po.CVE-2026-28421 2021-03-22 10:02:42.000000000 +0100 ++++ vim82/src/po/eo.po 2026-03-19 10:52:18.095330396 +0100 +@@ -7874,3 +7874,6 @@ msgstr "gvim" + + msgid "Vim" + msgstr "Vim" ++ ++msgid "???ILLEGAL BLOCK NUMBER" ++msgstr "" +diff -up vim82/src/po/es.po.CVE-2026-28421 vim82/src/po/es.po +--- vim82/src/po/es.po.CVE-2026-28421 2021-03-22 10:02:42.000000000 +0100 ++++ vim82/src/po/es.po 2026-03-19 10:52:18.095330396 +0100 +@@ -6347,3 +6347,6 @@ msgid "search hit BOTTOM, continuing at + msgstr "La búsqueda ha llegado al FINAL, continuando desde el PRINCIPIO" + + ++ ++msgid "???ILLEGAL BLOCK NUMBER" ++msgstr "" +diff -up vim82/src/po/fi.po.CVE-2026-28421 vim82/src/po/fi.po +--- vim82/src/po/fi.po.CVE-2026-28421 2021-03-22 10:02:42.000000000 +0100 ++++ vim82/src/po/fi.po 2026-03-19 10:52:18.095330396 +0100 +@@ -6982,3 +6982,6 @@ msgid "" + msgstr "" + "Ei onnistuttu asettaman polkua: sys.path ei ole list\n" + "Lisää vim.VIM_SPECIAL_PATH muuttujaan sys.path" ++ ++msgid "???ILLEGAL BLOCK NUMBER" ++msgstr "" +diff -up vim82/src/po/fr.po.CVE-2026-28421 vim82/src/po/fr.po +--- vim82/src/po/fr.po.CVE-2026-28421 2021-03-22 10:02:42.000000000 +0100 ++++ vim82/src/po/fr.po 2026-03-19 10:42:50.117725505 +0100 +@@ -8227,3 +8227,6 @@ msgstr "nom de la bibliothque dynamique + + msgid "name of the MzScheme dynamic library" + msgstr "nom de la bibliothque dynamique MzScheme" ++ ++msgid "???ILLEGAL BLOCK NUMBER" ++msgstr "" +diff -up vim82/src/po/ga.po.CVE-2026-28421 vim82/src/po/ga.po +--- vim82/src/po/ga.po.CVE-2026-28421 2021-03-22 10:02:42.000000000 +0100 ++++ vim82/src/po/ga.po 2026-03-19 10:52:18.095330396 +0100 +@@ -7461,3 +7461,6 @@ msgstr "" + + #~ msgid "E363: pattern caused out-of-stack error" + #~ msgstr "E363: ghin an patrn earrid as-an-chruach" ++ ++msgid "???ILLEGAL BLOCK NUMBER" ++msgstr "" +diff -up vim82/src/po/it.po.CVE-2026-28421 vim82/src/po/it.po +--- vim82/src/po/it.po.CVE-2026-28421 2021-03-22 10:02:42.000000000 +0100 ++++ vim82/src/po/it.po 2026-03-19 10:52:18.095330396 +0100 +@@ -6718,3 +6718,6 @@ msgstr "" + "Sorgenti C (*.c, *.h)\t*.c;*.h\n" + "Sorgenti C++ (*.cpp, *.hpp)\t*.cpp;*.hpp\n" + "File di Vim (*.vim, _vimrc, _gvimrc)\t*.vim;_vimrc;_gvimrc\n" ++ ++msgid "???ILLEGAL BLOCK NUMBER" ++msgstr "" +diff -up vim82/src/po/ja.euc-jp.po.CVE-2026-28421 vim82/src/po/ja.euc-jp.po +--- vim82/src/po/ja.euc-jp.po.CVE-2026-28421 2021-03-22 10:02:42.000000000 +0100 ++++ vim82/src/po/ja.euc-jp.po 2026-03-19 10:52:18.095330396 +0100 +@@ -7350,3 +7350,6 @@ msgstr "ƥ;ǥ;" + + #~ msgid "Vim" + #~ msgstr "" ++ ++msgid "???ILLEGAL BLOCK NUMBER" ++msgstr "" +diff -up vim82/src/po/ja.po.CVE-2026-28421 vim82/src/po/ja.po +--- vim82/src/po/ja.po.CVE-2026-28421 2021-03-22 10:02:42.000000000 +0100 ++++ vim82/src/po/ja.po 2026-03-19 10:52:18.095330396 +0100 +@@ -7350,3 +7350,6 @@ msgstr "テキスト;エディタ;" + + #~ msgid "Vim" + #~ msgstr "" ++ ++msgid "???ILLEGAL BLOCK NUMBER" ++msgstr "" +diff -up vim82/src/po/ja.sjis.po.CVE-2026-28421 vim82/src/po/ja.sjis.po +--- vim82/src/po/ja.sjis.po.CVE-2026-28421 2021-03-22 10:02:43.000000000 +0100 ++++ vim82/src/po/ja.sjis.po 2026-03-19 10:52:18.095330396 +0100 +@@ -7350,3 +7350,6 @@ msgstr "eLXg;GfB^;" + + #~ msgid "Vim" + #~ msgstr "" ++ ++msgid "???ILLEGAL BLOCK NUMBER" ++msgstr "" +diff -up vim82/src/po/ko.po.CVE-2026-28421 vim82/src/po/ko.po +--- vim82/src/po/ko.po.CVE-2026-28421 2021-03-22 10:02:42.000000000 +0100 ++++ vim82/src/po/ko.po 2026-03-19 10:42:50.120590463 +0100 +@@ -7002,3 +7002,6 @@ msgstr "" + "C ҽ (*.c, *.h)\t*.c;*.h\n" + "C++ ҽ (*.cpp, *.hpp)\t*.cpp;*.hpp\n" + "Vim (*.vim, _vimrc, _gvimrc)\t*.vim;_vimrc;_gvimrc\n" ++ ++msgid "???ILLEGAL BLOCK NUMBER" ++msgstr "" +diff -up vim82/src/po/ko.UTF-8.po.CVE-2026-28421 vim82/src/po/ko.UTF-8.po +--- vim82/src/po/ko.UTF-8.po.CVE-2026-28421 2021-03-22 10:02:42.000000000 +0100 ++++ vim82/src/po/ko.UTF-8.po 2026-03-19 10:42:50.120259142 +0100 +@@ -7002,3 +7002,6 @@ msgstr "" + "C 소스 (*.c, *.h)\t*.c;*.h\n" + "C++ 소스 (*.cpp, *.hpp)\t*.cpp;*.hpp\n" + "Vim 파일 (*.vim, _vimrc, _gvimrc)\t*.vim;_vimrc;_gvimrc\n" ++ ++msgid "???ILLEGAL BLOCK NUMBER" ++msgstr "" +diff -up vim82/src/po/lv.po.CVE-2026-28421 vim82/src/po/lv.po +--- vim82/src/po/lv.po.CVE-2026-28421 2021-03-22 10:02:42.000000000 +0100 ++++ vim82/src/po/lv.po 2026-03-19 10:42:50.120824441 +0100 +@@ -279,3 +279,6 @@ msgstr "E442: Nevar sadalīt kreiso aug + #, c-format + msgid "E447: Can't find file \"%s\" in path" + msgstr "E447: Failu \"%s\" ceļā nevar atrast" ++ ++msgid "???ILLEGAL BLOCK NUMBER" ++msgstr "" +diff -up vim82/src/po/nb.po.CVE-2026-28421 vim82/src/po/nb.po +--- vim82/src/po/nb.po.CVE-2026-28421 2021-03-22 10:02:42.000000000 +0100 ++++ vim82/src/po/nb.po 2026-03-19 10:42:50.120985413 +0100 +@@ -6121,3 +6121,6 @@ msgstr "Sket traff TOPPEN, fortsetter f + + msgid "search hit BOTTOM, continuing at TOP" + msgstr "Sket traff BUNNEN, fortsetter fra TOPPEN" ++ ++msgid "???ILLEGAL BLOCK NUMBER" ++msgstr "" +diff -up vim82/src/po/nl.po.CVE-2026-28421 vim82/src/po/nl.po +--- vim82/src/po/nl.po.CVE-2026-28421 2021-03-22 10:02:42.000000000 +0100 ++++ vim82/src/po/nl.po 2026-03-19 10:42:50.121281247 +0100 +@@ -5830,3 +5830,6 @@ msgstr "\" Druk op op een index + + msgid "\" Hit on a \"set\" line to refresh it." + msgstr "\" Druk op op een \"set\" regel om te verversen." ++ ++msgid "???ILLEGAL BLOCK NUMBER" ++msgstr "" +diff -up vim82/src/po/no.po.CVE-2026-28421 vim82/src/po/no.po +--- vim82/src/po/no.po.CVE-2026-28421 2021-03-22 10:02:42.000000000 +0100 ++++ vim82/src/po/no.po 2026-03-19 10:42:50.121569427 +0100 +@@ -6121,3 +6121,6 @@ msgstr "Sket traff TOPPEN, fortsetter f + + msgid "search hit BOTTOM, continuing at TOP" + msgstr "Sket traff BUNNEN, fortsetter fra TOPPEN" ++ ++msgid "???ILLEGAL BLOCK NUMBER" ++msgstr "" +diff -up vim82/src/po/pl.cp1250.po.CVE-2026-28421 vim82/src/po/pl.cp1250.po +--- vim82/src/po/pl.cp1250.po.CVE-2026-28421 2021-03-22 10:02:43.000000000 +0100 ++++ vim82/src/po/pl.cp1250.po 2026-03-19 10:42:50.122232088 +0100 +@@ -6860,3 +6860,6 @@ msgstr "" + + #~ msgid "E569: maximum number of cscope connections reached" + #~ msgstr "E569: wyczerpano maksymaln liczb pocze cscope" ++ ++msgid "???ILLEGAL BLOCK NUMBER" ++msgstr "" +diff -up vim82/src/po/pl.po.CVE-2026-28421 vim82/src/po/pl.po +--- vim82/src/po/pl.po.CVE-2026-28421 2021-03-22 10:02:42.000000000 +0100 ++++ vim82/src/po/pl.po 2026-03-19 10:42:50.122584749 +0100 +@@ -6860,3 +6860,6 @@ msgstr "" + + #~ msgid "E569: maximum number of cscope connections reached" + #~ msgstr "E569: wyczerpano maksymaln liczb pocze cscope" ++ ++msgid "???ILLEGAL BLOCK NUMBER" ++msgstr "" +diff -up vim82/src/po/pl.UTF-8.po.CVE-2026-28421 vim82/src/po/pl.UTF-8.po +--- vim82/src/po/pl.UTF-8.po.CVE-2026-28421 2021-03-22 10:02:42.000000000 +0100 ++++ vim82/src/po/pl.UTF-8.po 2026-03-19 10:42:50.121888304 +0100 +@@ -6860,3 +6860,6 @@ msgstr "" + + #~ msgid "E569: maximum number of cscope connections reached" + #~ msgstr "E569: wyczerpano maksymalną liczbę połączeń cscope" ++ ++msgid "???ILLEGAL BLOCK NUMBER" ++msgstr "" +diff -up vim82/src/po/pt_BR.po.CVE-2026-28421 vim82/src/po/pt_BR.po +--- vim82/src/po/pt_BR.po.CVE-2026-28421 2021-03-22 10:02:42.000000000 +0100 ++++ vim82/src/po/pt_BR.po 2026-03-19 10:42:50.122933262 +0100 +@@ -7005,3 +7005,6 @@ msgid "" + msgstr "" + "Falha ao definir path: sys.path não é uma lista\n" + "Você deve adicionar vim.VIM_SPECIAL_PATH ao sys.path" ++ ++msgid "???ILLEGAL BLOCK NUMBER" ++msgstr "" +diff -up vim82/src/po/ru.cp1251.po.CVE-2026-28421 vim82/src/po/ru.cp1251.po +--- vim82/src/po/ru.cp1251.po.CVE-2026-28421 2021-03-22 10:02:43.000000000 +0100 ++++ vim82/src/po/ru.cp1251.po 2026-03-19 10:52:18.095330396 +0100 +@@ -7482,3 +7482,6 @@ msgstr "gvim" + + msgid "Vim" + msgstr "Vim" ++ ++msgid "???ILLEGAL BLOCK NUMBER" ++msgstr "" +diff -up vim82/src/po/ru.po.CVE-2026-28421 vim82/src/po/ru.po +--- vim82/src/po/ru.po.CVE-2026-28421 2021-03-22 10:02:42.000000000 +0100 ++++ vim82/src/po/ru.po 2026-03-19 10:52:18.095330396 +0100 +@@ -7482,3 +7482,6 @@ msgstr "gvim" + + msgid "Vim" + msgstr "Vim" ++ ++msgid "???ILLEGAL BLOCK NUMBER" ++msgstr "" +diff -up vim82/src/po/sk.cp1250.po.CVE-2026-28421 vim82/src/po/sk.cp1250.po +--- vim82/src/po/sk.cp1250.po.CVE-2026-28421 2021-03-22 10:02:43.000000000 +0100 ++++ vim82/src/po/sk.cp1250.po 2026-03-19 10:52:18.095330396 +0100 +@@ -5776,3 +5776,6 @@ msgstr "hadanie dosiahlo zaiatok, pokr + msgid "search hit BOTTOM, continuing at TOP" + msgstr "hadanie dosiahlo koniec, pokraovanie od zaiatku" + ++ ++msgid "???ILLEGAL BLOCK NUMBER" ++msgstr "" +diff -up vim82/src/po/sk.po.CVE-2026-28421 vim82/src/po/sk.po +--- vim82/src/po/sk.po.CVE-2026-28421 2021-03-22 10:02:42.000000000 +0100 ++++ vim82/src/po/sk.po 2026-03-19 10:52:18.095330396 +0100 +@@ -5776,3 +5776,6 @@ msgstr "hadanie dosiahlo zaiatok, pokr + msgid "search hit BOTTOM, continuing at TOP" + msgstr "hadanie dosiahlo koniec, pokraovanie od zaiatku" + ++ ++msgid "???ILLEGAL BLOCK NUMBER" ++msgstr "" +diff -up vim82/src/po/sr.po.CVE-2026-28421 vim82/src/po/sr.po +--- vim82/src/po/sr.po.CVE-2026-28421 2021-03-22 10:02:42.000000000 +0100 ++++ vim82/src/po/sr.po 2026-03-19 10:52:18.095330396 +0100 +@@ -9566,3 +9566,6 @@ msgstr "име MzScheme динамичк + + msgid "name of the MzScheme GC dynamic library" + msgstr "име MzScheme GC динамичке библиотеке" ++ ++msgid "???ILLEGAL BLOCK NUMBER" ++msgstr "" +diff -up vim82/src/po/sv.po.CVE-2026-28421 vim82/src/po/sv.po +--- vim82/src/po/sv.po.CVE-2026-28421 2021-03-22 10:02:42.000000000 +0100 ++++ vim82/src/po/sv.po 2026-03-19 10:42:50.125487116 +0100 +@@ -6103,3 +6103,6 @@ msgstr "skning ndde TOPPEN, fortstter + + msgid "search hit BOTTOM, continuing at TOP" + msgstr "skning ndde BOTTEN, forstter vid TOPPEN" ++ ++msgid "???ILLEGAL BLOCK NUMBER" ++msgstr "" +diff -up vim82/src/po/tr.po.CVE-2026-28421 vim82/src/po/tr.po +--- vim82/src/po/tr.po.CVE-2026-28421 2021-03-22 10:02:42.000000000 +0100 ++++ vim82/src/po/tr.po 2026-03-19 10:52:18.095330396 +0100 +@@ -9368,3 +9368,6 @@ msgstr "MzScheme devingen kitaplığın + + msgid "name of the MzScheme GC dynamic library" + msgstr "MzScheme GC devingen kitaplığının adı" ++ ++msgid "???ILLEGAL BLOCK NUMBER" ++msgstr "" +diff -up vim82/src/po/uk.cp1251.po.CVE-2026-28421 vim82/src/po/uk.cp1251.po +--- vim82/src/po/uk.cp1251.po.CVE-2026-28421 2021-03-22 10:02:43.000000000 +0100 ++++ vim82/src/po/uk.cp1251.po 2026-03-19 10:52:18.095330396 +0100 +@@ -7324,3 +7324,6 @@ msgstr "" + " C (*.c, *.h)\t*.c;*.h\n" + " C++ (*.cpp, *.hpp)\t*.cpp;*.hpp\n" + " Vim (*.vim, _vimrc, _gvimrc)\t*.vim;_vimrc;_gvimrc\n" ++ ++msgid "???ILLEGAL BLOCK NUMBER" ++msgstr "" +diff -up vim82/src/po/uk.po.CVE-2026-28421 vim82/src/po/uk.po +--- vim82/src/po/uk.po.CVE-2026-28421 2021-03-22 10:02:42.000000000 +0100 ++++ vim82/src/po/uk.po 2026-03-19 10:52:18.095330396 +0100 +@@ -7324,3 +7324,6 @@ msgstr "" + "Першокод C (*.c, *.h)\t*.c;*.h\n" + "Першокод C++ (*.cpp, *.hpp)\t*.cpp;*.hpp\n" + "Файли Vim (*.vim, _vimrc, _gvimrc)\t*.vim;_vimrc;_gvimrc\n" ++ ++msgid "???ILLEGAL BLOCK NUMBER" ++msgstr "" +diff -up vim82/src/po/vi.po.CVE-2026-28421 vim82/src/po/vi.po +--- vim82/src/po/vi.po.CVE-2026-28421 2021-03-22 10:02:42.000000000 +0100 ++++ vim82/src/po/vi.po 2026-03-19 10:42:50.127177964 +0100 +@@ -5155,3 +5155,6 @@ msgstr "E449: Nhận được một bi + + msgid "E463: Region is guarded, cannot modify" + msgstr "E463: Không thể thay đổi vùng đã được bảo vệ" ++ ++msgid "???ILLEGAL BLOCK NUMBER" ++msgstr "" +diff -up vim82/src/po/zh_CN.cp936.po.CVE-2026-28421 vim82/src/po/zh_CN.cp936.po +--- vim82/src/po/zh_CN.cp936.po.CVE-2026-28421 2021-03-22 10:02:43.000000000 +0100 ++++ vim82/src/po/zh_CN.cp936.po 2026-03-19 10:52:18.095330396 +0100 +@@ -6097,3 +6097,6 @@ msgstr "Ѳҵļβٴӿͷ + + #~ msgid "with BeOS GUI." + #~ msgstr "ʹ BeOS ͼν档" ++ ++msgid "???ILLEGAL BLOCK NUMBER" ++msgstr "" +diff -up vim82/src/po/zh_CN.po.CVE-2026-28421 vim82/src/po/zh_CN.po +--- vim82/src/po/zh_CN.po.CVE-2026-28421 2021-03-22 10:02:42.000000000 +0100 ++++ vim82/src/po/zh_CN.po 2026-03-19 10:52:18.095330396 +0100 +@@ -6097,3 +6097,6 @@ msgstr "Ѳҵļβٴӿͷ + + #~ msgid "with BeOS GUI." + #~ msgstr "ʹ BeOS ͼν档" ++ ++msgid "???ILLEGAL BLOCK NUMBER" ++msgstr "" +diff -up vim82/src/po/zh_CN.UTF-8.po.CVE-2026-28421 vim82/src/po/zh_CN.UTF-8.po +--- vim82/src/po/zh_CN.UTF-8.po.CVE-2026-28421 2021-03-22 10:02:42.000000000 +0100 ++++ vim82/src/po/zh_CN.UTF-8.po 2026-03-19 10:52:18.095330396 +0100 +@@ -6097,3 +6097,6 @@ msgstr "已查找到文件结尾,再 + + #~ msgid "with BeOS GUI." + #~ msgstr "使用 BeOS 图形界面。" ++ ++msgid "???ILLEGAL BLOCK NUMBER" ++msgstr "" +diff -up vim82/src/po/zh_TW.po.CVE-2026-28421 vim82/src/po/zh_TW.po +--- vim82/src/po/zh_TW.po.CVE-2026-28421 2021-03-22 10:02:42.000000000 +0100 ++++ vim82/src/po/zh_TW.po 2026-03-19 10:42:50.128612401 +0100 +@@ -5223,3 +5223,6 @@ msgstr "E463: ϰQO@ALkק" + + #~ msgid "Retrieve next symbol" + #~ msgstr "Ū: qU symbol" ++ ++msgid "???ILLEGAL BLOCK NUMBER" ++msgstr "" +diff -up vim82/src/po/zh_TW.UTF-8.po.CVE-2026-28421 vim82/src/po/zh_TW.UTF-8.po +--- vim82/src/po/zh_TW.UTF-8.po.CVE-2026-28421 2021-03-22 10:02:42.000000000 +0100 ++++ vim82/src/po/zh_TW.UTF-8.po 2026-03-19 10:42:50.128380597 +0100 +@@ -5230,3 +5230,6 @@ msgstr "E463: 區域被保護,無法 + + #~ msgid "Retrieve next symbol" + #~ msgstr "讀取: 從下個 symbol" ++ ++msgid "???ILLEGAL BLOCK NUMBER" ++msgstr "" diff --git a/SOURCES/0001-patch-9.2.0089-netrw-does-not-take-port-into-account.patch b/SOURCES/0001-patch-9.2.0089-netrw-does-not-take-port-into-account.patch new file mode 100644 index 00000000..15abf6ce --- /dev/null +++ b/SOURCES/0001-patch-9.2.0089-netrw-does-not-take-port-into-account.patch @@ -0,0 +1,39 @@ +diff -up vim91/runtime/autoload/netrw.vim.validateportnum vim91/runtime/autoload/netrw.vim +--- vim91/runtime/autoload/netrw.vim.validateportnum 2026-03-17 19:35:34.062575124 +0100 ++++ vim91/runtime/autoload/netrw.vim 2026-03-17 19:39:39.005999509 +0100 +@@ -3376,7 +3376,8 @@ endif + + " s:NetrwValidateHostname: Validate that the hostname is valid {{{2 + " Input: +-" hostname, may include an optional username, e.g. user@hostname ++" hostname, may include an optional username and port number, e.g. ++" user@hostname:port + " allow a alphanumeric hostname or an IPv(4/6) address + " Output: + " true if g:netrw_machine is valid according to RFC1123 #Section 2 +@@ -3385,17 +3386,19 @@ fun! s:NetrwValidateHostname(hostname) + let user_pat = '\%([a-zA-Z0-9._-]\+@\)\?' + " Hostname: 1-64 chars, alphanumeric/dots/hyphens. + " No underscores. No leading/trailing dots/hyphens. +- let host_pat = '[a-zA-Z0-9]\%([-a-zA-Z0-9.]{,62}[a-zA-Z0-9]\)\?$' ++ let host_pat = '[a-zA-Z0-9]\%([-a-zA-Z0-9.]\{0,62}[a-zA-Z0-9]\)\?' ++ " Port: 16 bit unsigned integer ++ let port_pat = '\%(:\d\{1,5\}\)\?$' + + " IPv4: 1-3 digits separated by dots +- let ipv4_pat = '\%(\d\{1,3}\.\)\{3\}\d\{1,3\}$' ++ let ipv4_pat = '\%(\d\{1,3}\.\)\{3\}\d\{1,3\}' + + " IPv6: Hex, colons, and optional brackets +- let ipv6_pat = '\[\?\%([a-fA-F0-9:]\{2,}\)\+\]\?$' ++ let ipv6_pat = '\[\?\%([a-fA-F0-9:]\{2,}\)\+\]\?' + +- return a:hostname =~? '^'.user_pat.host_pat || +- \ a:hostname =~? '^'.user_pat.ipv4_pat || +- \ a:hostname =~? '^'.user_pat.ipv6_pat ++ return a:hostname =~? '^'.user_pat.host_pat.port_pat || ++ \ a:hostname =~? '^'.user_pat.ipv4_pat.port_pat || ++ \ a:hostname =~? '^'.user_pat.ipv6_pat.port_pat + endfun + + " --------------------------------------------------------------------- diff --git a/SOURCES/0001-runtime-netrw-upstream-snapshot-of-v179.patch b/SOURCES/0001-runtime-netrw-upstream-snapshot-of-v179.patch new file mode 100644 index 00000000..f62fb1ac --- /dev/null +++ b/SOURCES/0001-runtime-netrw-upstream-snapshot-of-v179.patch @@ -0,0 +1,65 @@ +diff -up vim91/runtime/autoload/netrw.vim.validatehostname vim91/runtime/autoload/netrw.vim +--- vim91/runtime/autoload/netrw.vim.validatehostname 2024-02-09 06:33:54.000000000 +0100 ++++ vim91/runtime/autoload/netrw.vim 2026-03-17 19:16:22.210561235 +0100 +@@ -1453,6 +1453,10 @@ fun! netrw#Obtain(islocal,fname,...) + call s:SetupNetrwStatusLine('%f %h%m%r%=%9*Obtaining '.a:fname) + endif + call s:NetrwMethod(b:netrw_curdir) ++ if !s:NetrwValidateHostname(g:netrw_machine) ++ call netrw#ErrorMsg(s:ERROR,"Rejecting invalid hostname: <" .. g:netrw_machine .. ">",107) ++ return ++ endif + + if b:netrw_method == 4 + " obtain file using scp +@@ -2143,6 +2147,10 @@ fun! netrw#NetRead(mode,...) + " call Dret("netrw#NetRead : unsupported method") + return + endif ++ if !s:NetrwValidateHostname(g:netrw_machine) ++ call netrw#ErrorMsg(s:ERROR,"Rejecting invalid hostname: <" .. g:netrw_machine .. ">",107) ++ return ++ endif + let tmpfile= s:GetTempfile(b:netrw_fname) " apply correct suffix + + " Check whether or not NetrwBrowse() should be handling this request +@@ -2565,6 +2573,10 @@ fun! netrw#NetWrite(...) range + " call Dfunc("netrw#NetWrite : unsupported method") + return + endif ++ if !s:NetrwValidateHostname(g:netrw_machine) ++ call netrw#ErrorMsg(s:ERROR,"Rejecting invalid hostname: <" .. g:netrw_machine .. ">",107) ++ return ++ endif + + " ============= + " NetWrite: Perform Protocol-Based Write {{{3 +@@ -3362,6 +3374,17 @@ if has("win95") && exists("g:netrw_win95 + endfun + endif + ++" s:NetrwValidateHostname: Validate that the hostname is valid {{{2 ++" Input: ++" hostname ++" Output: ++" true if g:netrw_machine is valid according to RFC1123 #Section 2 ++fun! s:NetrwValidateHostname(hostname) ++ " RFC1123#section-2 mandates, a valid hostname starts with letters or digits ++ " so reject everyhing else ++ return a:hostname =~? '^[a-z0-9]' ++endfun ++ + " --------------------------------------------------------------------- + " NetUserPass: set username and password for subsequent ftp transfer {{{2 + " Usage: :call NetUserPass() -- will prompt for userid and password +@@ -8842,6 +8865,10 @@ fun! s:NetrwUpload(fname,tgt,...) + + elseif a:tgt =~ '^ftp:' + call s:NetrwMethod(a:tgt) ++ if !s:NetrwValidateHostname(g:netrw_machine) ++ call netrw#ErrorMsg(s:ERROR,"Rejecting invalid hostname: <" .. g:netrw_machine .. ">",107) ++ return ++ endif + + if b:netrw_method == 2 + " handle uploading a list of files via ftp+.netrc diff --git a/SOURCES/vi_wrapper b/SOURCES/vi_wrapper deleted file mode 100644 index 1bb1aece..00000000 --- a/SOURCES/vi_wrapper +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/sh - -# run vim if: -# - 'vi' command is used and 'vim' binary is available -# - 'vim' command is used -# NOTE: Set up a local alias if you want vim -> vi functionality. We will not -# do it globally, because it messes up with available startup options (see -# ':help starting', 'vi' is not capable of '-d'). The introducing an environment -# variable, which an user must set to get the feature, will do the same trick -# as setting an alias (needs user input, does not work with sudo), so it is left -# on user whether he decides to use an alias: -# -# alias vim=vi -# -# in bashrc file. - -if test -f /usr/bin/vim -then - exec /usr/bin/vim "$@" -fi - -# run vi otherwise -exec /usr/libexec/vi "$@" diff --git a/SOURCES/view_wrapper b/SOURCES/view_wrapper index 9e8d7207..a0b24c9d 100644 --- a/SOURCES/view_wrapper +++ b/SOURCES/view_wrapper @@ -7,4 +7,4 @@ then fi # run vi otherwise -exec /usr/libexec/vi -R "$@" +exec /usr/bin/vi -R "$@" diff --git a/SOURCES/vim-CVE-2023-4752.patch b/SOURCES/vim-CVE-2023-4752.patch new file mode 100644 index 00000000..a698a270 --- /dev/null +++ b/SOURCES/vim-CVE-2023-4752.patch @@ -0,0 +1,262 @@ +diff --git a/src/insexpand.c b/src/insexpand.c +index 8d76c68..2ce675d 100644 +--- a/src/insexpand.c ++++ b/src/insexpand.c +@@ -2162,7 +2162,8 @@ ins_compl_next_buf(buf_T *buf, int flag) + + if (flag == 'w') // just windows + { +- if (buf == curbuf || wp == NULL) // first call for this flag/expansion ++ if (buf == curbuf || !win_valid(wp)) ++ // first call for this flag/expansion or window was closed + wp = curwin; + while ((wp = (wp->w_next != NULL ? wp->w_next : firstwin)) != curwin + && wp->w_buffer->b_scanned) +@@ -2675,10 +2676,12 @@ ins_compl_get_exp(pos_T *ini) + { + static pos_T first_match_pos; + static pos_T last_match_pos; +- static char_u *e_cpt = (char_u *)""; // curr. entry in 'complete' ++ static char_u *e_cpt; // curr. entry in 'complete' ++ static char_u *e_cpt_copy; // copy of curr. entry in 'complete' + static int found_all = FALSE; // Found all matches of a + // certain type. + static buf_T *ins_buf = NULL; // buffer being scanned ++ static int st_cleared = FALSE; + + pos_T *pos; + char_u **matches; +@@ -2697,12 +2700,34 @@ ins_compl_get_exp(pos_T *ini) + + if (!compl_started) + { +- FOR_ALL_BUFFERS(ins_buf) +- ins_buf->b_scanned = 0; ++ buf_T *buf; ++ ++ FOR_ALL_BUFFERS(buf) ++ buf->b_scanned = 0; ++ if (!st_cleared) ++ { ++ // this code does not match upstream commit, upstream clears struct `st` ++ // which includes the members which are arguments of `CLEAR_FIELD()` macros ++ // below. The code below should do the same thing as upstream `CLEAR_FIELD(st)` ++ CLEAR_FIELD(e_cpt); ++ CLEAR_FIELD(e_cpt_copy); ++ CLEAR_FIELD(ins_buf); ++ CLEAR_FIELD(pos); ++ CLEAR_FIELD(set_match_pos); ++ CLEAR_FIELD(first_match_pos); ++ CLEAR_FIELD(last_match_pos); ++ CLEAR_FIELD(found_all); ++ CLEAR_FIELD(dict); ++ CLEAR_FIELD(dict_f); ++ st_cleared = TRUE; ++ } + found_all = FALSE; + ins_buf = curbuf; +- e_cpt = (compl_cont_status & CONT_LOCAL) +- ? (char_u *)"." : curbuf->b_p_cpt; ++ vim_free(e_cpt_copy); ++ // Make a copy of 'complete', if case the buffer is wiped out. ++ e_cpt_copy = vim_strsave((compl_cont_status & CONT_LOCAL) ++ ? (char_u *)"." : curbuf->b_p_cpt); ++ e_cpt = e_cpt_copy == NULL ? (char_u *)"" : e_cpt_copy; + last_match_pos = first_match_pos = *ini; + } + else if (ins_buf != curbuf && !buf_valid(ins_buf)) +@@ -3100,7 +3125,7 @@ ins_compl_get_exp(pos_T *ini) + else + { + // Mark a buffer scanned when it has been scanned completely +- if (type == 0 || type == CTRL_X_PATH_PATTERNS) ++ if (buf_valid(ins_buf) && (type == 0 || type == CTRL_X_PATH_PATTERNS)) + ins_buf->b_scanned = TRUE; + + compl_started = FALSE; +@@ -3210,6 +3235,7 @@ ins_compl_next( + int found_end = FALSE; + int advance; + int started = compl_started; ++ buf_T *orig_curbuf = curbuf; + + // When user complete function return -1 for findstart which is next + // time of 'always', compl_shown_match become NULL. +@@ -3342,6 +3368,13 @@ ins_compl_next( + } + } + ++ if (curbuf != orig_curbuf) ++ { ++ // In case some completion function switched buffer, don't want to ++ // insert the completion elsewhere. ++ return -1; ++ } ++ + // Insert the text of the new completion, or the compl_leader. + if (compl_no_insert && !started) + { +diff --git a/src/move.c b/src/move.c +index 8ac1d0e..55cbd24 100644 +--- a/src/move.c ++++ b/src/move.c +@@ -649,6 +649,7 @@ cursor_valid(void) + void + validate_cursor(void) + { ++ check_cursor_lnum(); + check_cursor_moved(curwin); + if ((curwin->w_valid & (VALID_WCOL|VALID_WROW)) != (VALID_WCOL|VALID_WROW)) + curs_columns(TRUE); +diff --git a/src/testdir/Make_all.mak b/src/testdir/Make_all.mak +index 108c528..e800864 100644 +--- a/src/testdir/Make_all.mak ++++ b/src/testdir/Make_all.mak +@@ -92,6 +92,7 @@ NEW_TESTS = \ + test_conceal \ + test_const \ + test_cpoptions \ ++ test_crash \ + test_crypt \ + test_cscope \ + test_cursor_func \ +@@ -348,6 +349,7 @@ NEW_TESTS_RES = \ + test_conceal.res \ + test_const.res \ + test_cpoptions.res \ ++ test_crash.res \ + test_crypt.res \ + test_cscope.res \ + test_cursor_func.res \ +diff --git a/src/testdir/crash/poc_tagfunc.vim b/src/testdir/crash/poc_tagfunc.vim +new file mode 100644 +index 0000000..49d9b6f +--- /dev/null ++++ b/src/testdir/crash/poc_tagfunc.vim +@@ -0,0 +1,6 @@ ++fu Tagfunc(t,f,o) ++ bw ++endf ++set tagfunc=Tagfunc ++n0 ++sil0norm0i +diff --git a/src/testdir/term_util.vim b/src/testdir/term_util.vim +index 8541ef3..3a06019 100644 +--- a/src/testdir/term_util.vim ++++ b/src/testdir/term_util.vim +@@ -54,6 +54,7 @@ endfunc + " "cols" - width of the terminal window (max. 78) + " "statusoff" - number of lines the status is offset from default + " "wait_for_ruler" - if zero then don't wait for ruler to show ++" "cmd" - run any other command, e.g. "xxd" (used in xxd test) + func RunVimInTerminal(arguments, options) + " If Vim doesn't exit a swap file remains, causing other tests to fail. + " Remove it here. +@@ -88,7 +89,11 @@ func RunVimInTerminal(arguments, options) + let reset_u7 = ' --cmd "set t_u7=" ' + endif + +- let cmd = GetVimCommandCleanTerm() .. reset_u7 .. a:arguments ++ if empty(get(a:options, 'cmd', '')) ++ let cmd = GetVimCommandCleanTerm() .. reset_u7 .. a:arguments ++ else ++ let cmd = get(a:options, 'cmd') ++ endif + + let options = #{curwin: 1} + if &termwinsize == '' +@@ -114,7 +119,7 @@ func RunVimInTerminal(arguments, options) + + call TermWait(buf) + +- if get(a:options, 'wait_for_ruler', 1) ++ if get(a:options, 'wait_for_ruler', 1) && empty(get(a:options, 'cmd', '')) + " Wait for "All" or "Top" of the ruler to be shown in the last line or in + " the status line of the last window. This can be quite slow (e.g. when + " using valgrind). +diff --git a/src/testdir/test_crash.vim b/src/testdir/test_crash.vim +new file mode 100644 +index 0000000..4be1b49 +--- /dev/null ++++ b/src/testdir/test_crash.vim +@@ -0,0 +1,40 @@ ++" Some tests, that used to crash Vim ++source check.vim ++source screendump.vim ++ ++CheckScreendump ++ ++func Test_crash1() ++ if !executable('sh') ++ throw 'Skipped: sh not executable!' ++ endif ++ " The following used to crash Vim ++ let opts = #{cmd: 'sh'} ++ let vim = GetVimProg() ++ ++ let buf = RunVimInTerminal('sh', opts) ++ ++ let file = 'crash/poc_tagfunc.vim' ++ let cmn_args = "%s -u NONE -i NONE -n -e -s -S %s -c ':qa!'" ++ let args = printf(cmn_args, vim, file) ++ call term_sendkeys(buf, args .. ++ \ ' || echo "crash 5: [OK]" >> X_crash1_result.txt' .. "\") ++ ++ call TermWait(buf, 100) ++ ++ " clean up ++ exe buf .. "bw!" ++ ++ sp X_crash1_result.txt ++ ++ let expected = [ ++ \ 'crash 5: [OK]', ++ \ ] ++ ++ call assert_equal(expected, getline(1, '$')) ++ bw! ++ ++ call delete('X_crash1_result.txt') ++endfunc ++ ++" vim: shiftwidth=2 sts=2 expandtab +diff --git a/src/testdir/test_ins_complete.vim b/src/testdir/test_ins_complete.vim +index 613e952..24232d8 100644 +--- a/src/testdir/test_ins_complete.vim ++++ b/src/testdir/test_ins_complete.vim +@@ -496,9 +496,8 @@ func Test_pum_with_preview_win() + + call writefile(lines, 'Xpreviewscript') + let buf = RunVimInTerminal('-S Xpreviewscript', #{rows: 12}) +- call TermWait(buf, 50) + call term_sendkeys(buf, "Gi\\") +- call TermWait(buf, 100) ++ call TermWait(buf, 200) + call term_sendkeys(buf, "\") + call VerifyScreenDump(buf, 'Test_pum_with_preview_win', {}) + +@@ -724,7 +723,23 @@ func Test_z1_complete_no_history() + exe "normal owh\\" + exe "normal owh\" + call assert_equal(currmess, execute('messages')) +- close! ++ bwipe! ++endfunc ++ ++func s:Tagfunc(t,f,o) ++ bwipe! ++ return [] ++endfunc ++ ++" This was using freed memory, since 'complete' was in a wiped out buffer. ++" Also using a window that was closed. ++func Test_tagfunc_wipes_out_buffer() ++ new ++ set complete=.,t,w,b,u,i ++ se tagfunc=s:Tagfunc ++ sil norm i␎ ++ bwipe! + endfunc + ++ + " vim: shiftwidth=2 sts=2 expandtab diff --git a/SPECS/vim.spec b/SPECS/vim.spec index c7125b99..0dbafd99 100644 --- a/SPECS/vim.spec +++ b/SPECS/vim.spec @@ -27,7 +27,7 @@ Summary: The VIM editor URL: http://www.vim.org/ Name: vim Version: %{baseversion}.%{patchlevel} -Release: 21%{?dist} +Release: 26%{?dist} License: Vim and MIT Source0: ftp://ftp.vim.org/pub/vim/unix/vim-%{baseversion}-%{patchlevel}.tar.bz2 Source1: virc @@ -42,7 +42,6 @@ Source9: vim-default-editor.sh Source10: vim-default-editor.csh Source11: vim-default-editor.fish Source12: view_wrapper -Source13: vi_wrapper %if %{withvimspell} Source100: vim-spell-files.tar.bz2 @@ -138,6 +137,41 @@ Patch3052: 0001-patch-8.2.5037-cursor-position-may-be-invalid-after-.patch Patch3053:0001-patch-9.0.0339-no-check-if-the-return-value-of-XChan.patch # RHEL-40602 CVE-2021-3903 vim: heap-based buffer overflow vulnerability Patch3054: 0001-patch-8.2.3564-invalid-memory-access-when-scrolling-.patch +# RHEL-2159 vim: Heap Use After Free in function ins_compl_get_exp in vim/vim +# combined patch of some parts of the following commits: +# https://github.com/vim/vim/commit/e1dc9a6275 +# https://github.com/vim/vim/commit/ee9166eb3b +# https://github.com/vim/vim/commit/0ff01835a4 +# https://github.com/vim/vim/commit/d4566c14e7 +# https://github.com/vim/vim/commit/d979d64fa2 +# https://github.com/vim/vim/commit/e2528ae111 +Patch3055: vim-CVE-2023-4752.patch +# RHEL-112005 CVE-2025-53905 vim: Vim path traversial +Patch3056: 0001-patch-9.1.1552-security-path-traversal-issue-in-tar..patch +# RHEL-112009 CVE-2025-53906 vim: Vim path traversal +Patch3057: 0001-patch-9.1.1551-security-path-traversal-issue-in-zip..patch +# RHEL-147941 CVE-2026-25749 vim: Heap Overflow in Vim +# 0001-patch-9.1.2132-security-buffer-overflow-in-helpfile-.patch +# 0001-patch-9.1.2133-Another-case-of-buffer-overflow-with-.patch +Patch3058: 0001-patch-9.1.2132-security-buffer-overflow-in-helpfile-.patch +Patch3059: 0001-patch-9.1.2133-Another-case-of-buffer-overflow-with-.patch +# RHEL-155438 CVE-2026-28417 vim: Vim: Arbitrary code execution via OS command injection in the netrw plugin +# 3 patches: +# 0001-runtime-netrw-upstream-snapshot-of-v179.patch - introduces NetrwValidateHostname +# 0001-patch-9.2.0073-security-possible-command-injection-u.patch - CVE patch which sanitizes hostnames +# and reports invalid characters in SSH commands +# 0001-patch-9.2.0089-netrw-does-not-take-port-into-account.patch - include portnumber in hostname checking +Patch3060: 0001-runtime-netrw-upstream-snapshot-of-v179.patch +Patch3061: 0001-patch-9.2.0073-security-possible-command-injection-u.patch +Patch3062: 0001-patch-9.2.0089-netrw-does-not-take-port-into-account.patch +# RHEL-155423 CVE-2026-28421 vim: Vim: Denial of service and information disclosure via crafted swap file +# 0001-patch-9.0.1477-crash-when-recovering-from-corrupted-.patch - adds check for max page count, which fixes +# crash which happens after applying 0001-patch-9.2.0077-security-Crash-when-recovering-a-corr.patch +# 0001-patch-9.2.0077-security-Crash-when-recovering-a-corr.patch - validates line count and page count from +# untrusted swap file before passing it to read and allocation functions +Patch3063: 0001-patch-9.0.1477-crash-when-recovering-from-corrupted-.patch +Patch3064: 0001-patch-9.2.0077-security-Crash-when-recovering-a-corr.patch + # gcc is no longer in buildroot by default BuildRequires: gcc @@ -379,6 +413,16 @@ perl -pi -e "s,bin/nawk,bin/awk,g" runtime/tools/mve.awk %patch3052 -p1 -b .cve1927 %patch3053 -p1 -b .cve47024 %patch -P 3054 -p1 -b .cve2021-3903 +%patch -P 3055 -p1 -b .CVE-2023-4752 +%patch -P 3056 -p1 -b .CVE-2025-53905 +%patch -P 3057 -p1 -b .CVE-2025-53906 +%patch -P 3058 -p1 -b .tag-overflow +%patch -P 3059 -p1 -b .tag-overflow2 +%patch -P 3060 -p1 -b .validatehostname +%patch -P 3061 -p1 -b .CVE-2026-28417 +%patch -P 3062 -p1 -b .validateportnum +%patch -P 3063 -p1 -b .check-page-count +%patch -P 3064 -p1 -b .CVE-2026-28421 %build cd src @@ -387,8 +431,8 @@ autoconf sed -e "s+VIMRCLOC = \$(VIMLOC)+VIMRCLOC = /etc+" Makefile > Makefile.tmp mv -f Makefile.tmp Makefile -export CFLAGS="%{optflags} -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_FORTIFY_SOURCE=2" -export CXXFLAGS="%{optflags} -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_FORTIFY_SOURCE=2" +export CFLAGS="%{optflags} -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_FORTIFY_SOURCE=2 -O0" +export CXXFLAGS="%{optflags} -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_FORTIFY_SOURCE=2 -O0" cp -f os_unix.h os_unix.h.save cp -f ex_cmds.c ex_cmds.c.save @@ -522,17 +566,13 @@ cd src # and put the stripped files into correct dirs. Build system (koji/brew) # does it for us, so there is no need to do it in Vim %make_install BINDIR=%{_bindir} VIMRCLOC=/etc VIMRUNTIMEDIR=/usr/share/vim/%{vimdir} STRIP=/bin/true -# make install creates vim binary and view symlink, they will be wrappers -# so remove them here -%{_bindir}/rm -f %{buildroot}%{_bindir}/{vim,view} + make installgtutorbin DESTDIR=%{buildroot} BINDIR=%{_bindir} VIMRCLOC=/etc VIMRUNTIMEDIR=/usr/share/vim/%{vimdir} mkdir -p %{buildroot}%{_datadir}/icons/hicolor/{16x16,32x32,48x48,64x64}/apps -mkdir -p %{buildroot}%{_libexecdir} -install -m755 minimal-vim %{buildroot}%{_libexecdir}/vi +install -m755 minimal-vim %{buildroot}%{_bindir}/vi install -m755 enhanced-vim %{buildroot}%{_bindir}/vim install -m755 gvim %{buildroot}%{_bindir}/gvim install -m755 %{SOURCE12} %{buildroot}%{_bindir}/view -install -m755 %{SOURCE13} %{buildroot}%{_bindir}/vi install -p -m644 %{SOURCE3} \ %{buildroot}%{_datadir}/icons/hicolor/16x16/apps/gvim.png install -p -m644 %{SOURCE4} \ @@ -586,9 +626,9 @@ SentUpstream: 2014-05-22 EOF ( cd %{buildroot} - ln -sf %{_libexecdir}/vi .%{_bindir}/rvi - ln -sf %{_libexecdir}/vi .%{_bindir}/rview - ln -sf %{_libexecdir}/vi .%{_bindir}/ex + ln -sf %{_bindir}/vi .%{_bindir}/rvi + ln -sf %{_bindir}/vi .%{_bindir}/rview + ln -sf %{_bindir}/vi .%{_bindir}/ex ln -sf %{_bindir}/vim .%{_bindir}/rvim ln -sf %{_bindir}/vim .%{_bindir}/vimdiff perl -pi -e "s,%{buildroot},," .%{_mandir}/man1/vim.1 .%{_mandir}/man1/vimtutor.1 @@ -866,7 +906,6 @@ touch %{buildroot}/%{_datadir}/%{name}/vimfiles/doc/tags %{_bindir}/rview %{_bindir}/vi %{_bindir}/view -%{_libexecdir}/vi %{_mandir}/man1/vi.* %{_mandir}/man1/ex.* %{_mandir}/man1/rvi.* @@ -936,6 +975,23 @@ touch %{buildroot}/%{_datadir}/%{name}/vimfiles/doc/tags %endif %changelog +* Thu Mar 19 2026 Zdenek Dohnal - 2:8.2.2637-26 +- RHEL-155438 CVE-2026-28417 vim: Vim: Arbitrary code execution via OS command injection in the netrw plugin +- RHEL-155423 CVE-2026-28421 vim: Vim: Denial of service and information disclosure via crafted swap file + +* Tue Feb 10 2026 Zdenek Dohnal - 2:8.2.2637-25 +- RHEL-147941 CVE-2026-25749 vim: Heap Overflow in Vim + +* Mon Feb 02 2026 Zdenek Dohnal - 2:8.2.2637-24 +- RHEL-143726 sudo not able to spawn "vi" command when NOEXEC is used to prevent escaping to shell + +* Wed Sep 17 2025 Zdenek Dohnal - 2:8.2.2637-23 +- RHEL-112005 CVE-2025-53905 vim: Vim path traversial +- RHEL-112009 CVE-2025-53906 vim: Vim path traversal + +* Tue Feb 25 2025 Zdenek Dohnal - 2:8.2.2637-22 +- RHEL-2159 vim: Heap Use After Free in function ins_compl_get_exp in vim/vim + * Mon Aug 05 2024 Zdenek Dohnal - 2:8.2.2637-21 - RHEL-40602 CVE-2021-3903 vim: heap-based buffer overflow vulnerability