diff --git a/0010-fix-CVE-2024-47814.patch b/0010-fix-CVE-2024-47814.patch new file mode 100644 index 0000000000000000000000000000000000000000..bda5a210677c02c17db499c0b2ddb3120767330d --- /dev/null +++ b/0010-fix-CVE-2024-47814.patch @@ -0,0 +1,101 @@ +From 51b62387be93c65fa56bbabe1c3c1ea5df187641 Mon Sep 17 00:00:00 2001 +From: Christian Brabandt +Date: Tue, 8 Oct 2024 09:24:30 +0800 +Subject: [PATCH] fix CVE-2024-47814 + +Problem: [security]: use-after-free when closing a buffer +Solution: When splitting the window and editing a new buffer, + check whether the newly to be edited buffer has been marked + for deletion and abort in this case + +Github Advisory: +https://github.com/vim/vim/security/advisories/GHSA-rj48-v4mq-j4vg + +Signed-off-by: Christian Brabandt + +--- + src/buffer.c | 6 ++++++ + src/ex_cmds.c | 12 ++++++++++++ + src/proto/buffer.pro | 1 + + src/testdir/test_autocmd.vim | 19 +++++++++++++++++++ + 4 files changed, 38 insertions(+) + +diff --git a/src/buffer.c b/src/buffer.c +index 260d22e..6bdb7a6 100644 +--- a/src/buffer.c ++++ b/src/buffer.c +@@ -496,6 +496,12 @@ can_unload_buffer(buf_T *buf) + return can_unload; + } + ++ int ++buf_locked(buf_T *buf) ++{ ++ return buf->b_locked || buf->b_locked_split; ++} ++ + /* + * Close the link to a buffer. + * "action" is used when there is no longer a window for the buffer. +diff --git a/src/ex_cmds.c b/src/ex_cmds.c +index 46c4503..31cef2a 100644 +--- a/src/ex_cmds.c ++++ b/src/ex_cmds.c +@@ -2740,6 +2740,18 @@ do_ecmd( + } + if (buf == NULL) + goto theend; ++ // autocommands try to edit a file that is goind to be removed, ++ // abort ++ if (buf_locked(buf)) ++ { ++ // window was split, but not editing the new buffer, ++ // reset b_nwindows again ++ if (oldwin == NULL ++ && curwin->w_buffer != NULL ++ && curwin->w_buffer->b_nwindows > 1) ++ --curwin->w_buffer->b_nwindows; ++ goto theend; ++ } + if (curwin->w_alt_fnum == buf->b_fnum && prev_alt_fnum != 0) + // reusing the buffer, keep the old alternate file + curwin->w_alt_fnum = prev_alt_fnum; +diff --git a/src/proto/buffer.pro b/src/proto/buffer.pro +index 3a61027..dc68ca8 100644 +--- a/src/proto/buffer.pro ++++ b/src/proto/buffer.pro +@@ -70,4 +70,5 @@ char_u *buf_get_fname(buf_T *buf); + void set_buflisted(int on); + int buf_contents_changed(buf_T *buf); + void wipe_buffer(buf_T *buf, int aucmd); ++int buf_locked(buf_T *buf); + /* vim: set ft=c : */ +diff --git a/src/testdir/test_autocmd.vim b/src/testdir/test_autocmd.vim +index 0652a6f..3abde1e 100644 +--- a/src/testdir/test_autocmd.vim ++++ b/src/testdir/test_autocmd.vim +@@ -4311,4 +4311,23 @@ func Test_autocmd_shortmess() + delfunc SetupVimTest_shm + endfunc + ++" This was using freed memory ++func Test_autocmd_BufWinLeave_with_vsp() ++ new ++ let fname = 'XXXBufWinLeaveUAF.txt' ++ let dummy = 'XXXDummy.txt' ++ call writefile([], fname) ++ call writefile([], dummy) ++ defer delete(fname) ++ defer delete(dummy) ++ exe "e " fname ++ vsp ++ augroup testing ++ exe "au BufWinLeave " .. fname .. " :e " dummy .. "| vsp " .. fname ++ augroup END ++ bw ++ call CleanUpTestAuGroup() ++ exe "bw! " .. dummy ++endfunc ++ + " vim: shiftwidth=2 sts=2 expandtab + diff --git a/0011-fix-CVE-2025-53906.patch b/0011-fix-CVE-2025-53906.patch new file mode 100644 index 0000000000000000000000000000000000000000..5f94c259485258e35f759cd21adb7ae367fee9ba --- /dev/null +++ b/0011-fix-CVE-2025-53906.patch @@ -0,0 +1,193 @@ +From 7a7ccc9094964524f6662be509cac952830350ed Mon Sep 17 00:00:00 2001 +From: Christian Brabandt +Date: Tue, 15 Jul 2025 21:43:01 +0200 +Subject: [PATCH] patch 9.1.1551: [security]: path traversal issue in zip.vim + +--- + runtime/autoload/zip.vim | 105 ++++++++++++++++++++------------------- + 1 file changed, 53 insertions(+), 52 deletions(-) + +diff --git a/runtime/autoload/zip.vim b/runtime/autoload/zip.vim +index e61293c..0d9984b 100644 +--- a/runtime/autoload/zip.vim ++++ b/runtime/autoload/zip.vim +@@ -266,37 +266,27 @@ 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\+.*$','','')) +- redraw! +- echohl Error | echo "***error*** (zip#Write) sorry, your system doesn't appear to have the ".g:zip_zipcmd." program" | echohl None +-" call inputsave()|call input("Press to continue")|call inputrestore() +- let &report= repkeep +-" 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 ++ redraw! ++ echohl Error | echo "***error*** (zip#Write) sorry, your system doesn't appear to have the ".g:zip_zipcmd." program" | echohl None ++ return + endif + + let curdir= getcwd() + let tmpdir= tempname() + " call Decho("orig tempname<".tmpdir.">") + if tmpdir =~ '\.' +- let tmpdir= substitute(tmpdir,'\.[^.]*$','','e') ++ let tmpdir= substitute(tmpdir,'\.[^.]*$','','e') + endif + " call Decho("tmpdir<".tmpdir.">") + call mkdir(tmpdir,"p") + + " attempt to change to the indicated directory + if s:ChgDir(tmpdir,s:ERROR,"(zip#Write) cannot cd to temporary directory") +- let &report= repkeep ++ let &report= repkeep + " call Dret("zip#Write") + return + endif +@@ -311,31 +301,37 @@ fun! zip#Write(fname) + " call Decho("current directory now: ".getcwd()) + + if has("unix") +- let zipfile = substitute(a:fname,'zipfile://\(.\{-}\)::[^\\].*$','\1','') +- let fname = substitute(a:fname,'zipfile://.\{-}::\([^\\].*\)$','\1','') ++ let zipfile = substitute(a:fname,'zipfile://\(.\{-}\)::[^\\].*$','\1','') ++ let fname = substitute(a:fname,'zipfile://.\{-}::\([^\\].*\)$','\1','') + else +- let zipfile = substitute(a:fname,'^.\{-}zipfile://\(.\{-}\)::[^\\].*$','\1','') +- let fname = substitute(a:fname,'^.\{-}zipfile://.\{-}::\([^\\].*\)$','\1','') ++ 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.">") + + if fname =~ '/' +- let dirpath = substitute(fname,'/[^/]\+$','','e') +- if has("win32unix") && executable("cygpath") +- let dirpath = substitute(system("cygpath ".s:Escape(dirpath,0)),'\n','','e') +- endif ++ let dirpath = substitute(fname,'/[^/]\+$','','e') ++ if has("win32unix") && executable("cygpath") ++ let dirpath = substitute(system("cygpath ".s:Escape(dirpath,0)),'\n','','e') ++ endif + " call Decho("mkdir(dirpath<".dirpath.">,p)") +- call mkdir(dirpath,"p") ++ call mkdir(dirpath,"p") + endif + if zipfile !~ '/' +- let zipfile= curdir.'/'.zipfile ++ let zipfile= curdir.'/'.zipfile + endif + " call Decho("zipfile<".zipfile."> fname<".fname.">") + +- exe "w! ".fnameescape(fname) ++ " don't overwrite files forcefully ++ exe "w ".fnameescape(fname) + if has("win32unix") && executable("cygpath") +- let zipfile = substitute(system("cygpath ".s:Escape(zipfile,0)),'\n','','e') ++ let zipfile = substitute(system("cygpath ".s:Escape(zipfile,0)),'\n','','e') + endif + + if (has("win32") || has("win95") || has("win64") || has("win16")) && &shell !~? 'sh$' +@@ -345,24 +341,27 @@ fun! zip#Write(fname) + " call Decho(g:zip_zipcmd." -u ".s:Escape(fnamemodify(zipfile,":p"),0)." ".s:Escape(fname,0)) + call system(g:zip_zipcmd." -u ".s:Escape(fnamemodify(zipfile,":p"),0)." ".s:Escape(fname,0)) + if v:shell_error != 0 +- redraw! +- echohl Error | echo "***error*** (zip#Write) sorry, unable to update ".zipfile." with ".fname | echohl None ++ redraw! ++ echohl Error | echo "***error*** (zip#Write) sorry, unable to update ".zipfile." with ".fname | echohl None + " call inputsave()|call input("Press to continue")|call inputrestore() + + elseif s:zipfile_{winnr()} =~ '^\a\+://' +- " support writing zipfiles across a network +- let netzipfile= s:zipfile_{winnr()} +-" call Decho("handle writing <".zipfile."> across network as <".netzipfile.">") +- 1split|enew +- let binkeep= &binary +- let eikeep = &ei +- set binary ei=all +- exe "noswapfile e! ".fnameescape(zipfile) +- call netrw#NetWrite(netzipfile) +- let &ei = eikeep +- let &binary = binkeep +- q! +- unlet s:zipfile_{winnr()} ++ " support writing zipfiles across a network ++ let netzipfile= s:zipfile_{winnr()} ++ 1split|enew ++ let binkeep= &binary ++ let eikeep = &ei ++ set binary ei=all ++ exe "noswapfile e! ".fnameescape(zipfile) ++ call netrw#NetWrite(netzipfile) ++ let &ei = eikeep ++ let &binary = binkeep ++ q! ++ unlet s:zipfile_{winnr()} ++ elseif need_rename ++ exe $"sil keepalt file {fnameescape($"zipfile://{zipfile}::{fname}")}" ++ redraw! ++ echohl WarningMsg | echo "***error*** (zip#Browse) Path Traversal Attack detected, dropping relative path" | echohl None + endif + + " cleanup and restore current directory +@@ -388,16 +387,18 @@ fun! zip#Extract() + + " sanity check + if fname =~ '^"' +- let &report= repkeep ++ let &report= repkeep + " call Dret("zip#Extract") + return + endif + if fname =~ '/$' +- redraw! +- echohl Error | echo "***error*** (zip#Extract) Please specify a file, not a directory" | echohl None +- let &report= repkeep +-" call Dret("zip#Extract") +- return ++ redraw! ++ echohl Error | echo "***error*** (zip#Extract) Please specify a file, not a directory" | echohl None ++ return ++ elseif fname =~ '^[.]\?[.]/' ++ redraw! ++ echohl Error | echo "***error*** (zip#Browse) Path Traversal Attack detected, not extracting!" | echohl None ++ return + endif + + " extract the file mentioned under the cursor +@@ -405,11 +406,11 @@ fun! zip#Extract() + call system(g:zip_extractcmd." ".shellescape(b:zipfile)." ".shellescape(shell)) + " call Decho("zipfile<".b:zipfile.">") + if v:shell_error != 0 +- echohl Error | echo "***error*** ".g:zip_extractcmd." ".b:zipfile." ".fname.": failed!" | echohl NONE ++ echohl Error | echo "***error*** ".g:zip_extractcmd." ".b:zipfile." ".fname.": failed!" | echohl NONE + elseif !filereadable(fname) +- echohl Error | echo "***error*** attempted to extract ".fname." but it doesn't appear to be present!" ++ echohl Error | echo "***error*** attempted to extract ".fname." but it doesn't appear to be present!" + else +- echo "***note*** successfully extracted ".fname ++ echo "***note*** successfully extracted ".fname + endif + + " restore option +-- +2.43.5 + diff --git a/0012-comment-out-strange-error-condition-check.patch b/0012-comment-out-strange-error-condition-check.patch new file mode 100644 index 0000000000000000000000000000000000000000..24001d889e2e82d905b55398d01569713fb74300 --- /dev/null +++ b/0012-comment-out-strange-error-condition-check.patch @@ -0,0 +1,67 @@ +From 67abf1592c83c910c7815478f67e0a8989d51417 Mon Sep 17 00:00:00 2001 +From: Christian Brabandt +Date: Tue, 14 Nov 2023 17:15:17 +0100 +Subject: [PATCH] runtime(tar): comment out strange error condition check + +Signed-off-by: Christian Brabandt +--- + runtime/autoload/tar.vim | 35 ++++++++++++++++------------------- + 1 file changed, 16 insertions(+), 19 deletions(-) + +diff --git a/runtime/autoload/tar.vim b/runtime/autoload/tar.vim +index 52369a42c1c1bf..adfc10c92bc99c 100644 +--- a/runtime/autoload/tar.vim ++++ b/runtime/autoload/tar.vim +@@ -1,7 +1,7 @@ + " tar.vim: Handles browsing tarfiles + " AUTOLOAD PORTION +-" Date: Nov 05, 2023 +-" Version: 32a (with modifications from the Vim Project) ++" Date: Nov 11, 2023 ++" Version: 32b (with modifications from the Vim Project) + " Maintainer: Charles E Campbell + " License: Vim License (see vim's :help license) + " +@@ -208,27 +208,24 @@ fun! tar#Browse(tarfile) + " call Dret("tar#Browse : a:tarfile<".a:tarfile.">") + return + endif +- " If there was an error message, the last line probably matches some keywords but +- " should also contain whitespace for readability. Make sure not to match a +- " filename that contains the keyword (error/warning/unrecognized/inappropriate, etc) + " + " FIXME:is this actually necessary? In case of an error, we should probably + " have noticed in the if statement above since tar should have exited + " with a non-zero exit code. +- if line("$") == curlast || ( line("$") == (curlast + 1) && +- \ getline("$") =~# '\c\<\%(warning\|error\|inappropriate\|unrecognized\)\>' && +- \ getline("$") =~ '\s' ) +- redraw! +- echohl WarningMsg | echo "***warning*** (tar#Browse) ".a:tarfile." doesn't appear to be a tar file" | echohl None +- keepj sil! %d +- let eikeep= &ei +- set ei=BufReadCmd,FileReadCmd +- exe "r ".fnameescape(a:tarfile) +- let &ei= eikeep +- keepj sil! 1d +-" call Dret("tar#Browse : a:tarfile<".a:tarfile.">") +- return +- endif ++ " if line("$") == curlast || ( line("$") == (curlast + 1) && ++ " \ getline("$") =~# '\c\<\%(warning\|error\|inappropriate\|unrecognized\)\>' && ++ " \ getline("$") =~ '\s' ) ++ " redraw! ++ " echohl WarningMsg | echo "***warning*** (tar#Browse) ".a:tarfile." doesn't appear to be a tar file" | echohl None ++ " keepj sil! %d ++ " let eikeep= &ei ++ " set ei=BufReadCmd,FileReadCmd ++ " exe "r ".fnameescape(a:tarfile) ++ " let &ei= eikeep ++ " keepj sil! 1d ++ " call Dret("tar#Browse : a:tarfile<".a:tarfile.">") ++ " return ++ " endif + + " set up maps supported for tar + setlocal noma nomod ro + diff --git a/0013-fix-a-few-problems-with-the-tar-plugin.patch b/0013-fix-a-few-problems-with-the-tar-plugin.patch new file mode 100644 index 0000000000000000000000000000000000000000..e2bd614458086dee70b0b8a53ae0066bbb472585 --- /dev/null +++ b/0013-fix-a-few-problems-with-the-tar-plugin.patch @@ -0,0 +1,118 @@ +From 3a5b3df7764daa058a3e779183e8f38a8418b164 Mon Sep 17 00:00:00 2001 +From: Christian Brabandt +Date: Mon, 8 Jan 2024 20:02:14 +0100 +Subject: [PATCH] runtime(tar): fix a few problems with the tar plugin + +From: #138331: + - Updating .tar.zst files was broken. Fixes #12639. + - Extracting files from .tar.zst / .tzs files was also broken and + works now. +From: #12637: + - Fixes variable assignment and typo +From: #8109: + - Rename .tzs to the more standard .tzst + +fixes: #12639 +fixes: #8105 +closes: #8109 +closes: #12637 +closes: #13831 + +Co-authored-by: Martin Rys +Co-authored-by: Eisuke Kawashima +Co-authored-by: Carlo Teubner +Signed-off-by: Christian Brabandt +--- + runtime/autoload/tar.vim | 24 ++++++++++++------------ + runtime/plugin/tarPlugin.vim | 2 +- + 2 files changed, 13 insertions(+), 13 deletions(-) + +diff --git a/runtime/autoload/tar.vim b/runtime/autoload/tar.vim +index adfc10c92bc99..3c4c9ccfb2e77 100644 +--- a/runtime/autoload/tar.vim ++++ b/runtime/autoload/tar.vim +@@ -163,9 +163,9 @@ fun! tar#Browse(tarfile) + " call Decho("1: exe silent r! gzip -d -c -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - ") + exe "sil! r! gzip -d -c -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - " + +- elseif tarfile =~# '\.\(tgz\)$' || tarfile =~# '\.\(tbz\)$' || tarfile =~# '\.\(txz\)$' || tarfile =~# '\.\(tzs\)$' ++ elseif tarfile =~# '\.\(tgz\)$' || tarfile =~# '\.\(tbz\)$' || tarfile =~# '\.\(txz\)$' || tarfile =~# '\.\(tzst\)$' + if has("unix") && executable("file") +- let filekind= system("file ".shellescape(tarfile,1)) =~ "bzip2" ++ let filekind= system("file ".shellescape(tarfile,1)) + else + let filekind= "" + endif +@@ -192,7 +192,7 @@ fun! tar#Browse(tarfile) + elseif tarfile =~# '\.\(xz\|txz\)$' + " call Decho("3: exe silent r! xz --decompress --stdout -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - ") + exe "sil! r! xz --decompress --stdout -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - " +- elseif tarfile =~# '\.\(zst\|tzs\)$' ++ elseif tarfile =~# '\.\(zst\|tzst\)$' + exe "sil! r! zstd --decompress --stdout -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - " + else + if tarfile =~ '^\s*-' +@@ -230,7 +230,7 @@ fun! tar#Browse(tarfile) + " set up maps supported for tar + setlocal noma nomod ro + noremap :call TarBrowseSelect() +- noremap x :call tar#Extract() ++ noremap x :call tar#Extract() + if &mouse != "" + noremap :call TarBrowseSelect() + endif +@@ -468,9 +468,9 @@ fun! tar#Write(fname) + let compress= "xz -- ".shellescape(tarfile,0) + " call Decho("compress<".compress.">") + elseif tarfile =~# '\.zst' +- call system("zstd --decompress -- ".shellescape(tarfile,0)) ++ call system("zstd --decompress --rm -- ".shellescape(tarfile,0)) + let tarfile = substitute(tarfile,'\.zst','','e') +- let compress= "zstd -- ".shellescape(tarfile,0) ++ let compress= "zstd --rm -- ".shellescape(tarfile,0) + elseif tarfile =~# '\.lzma' + call system("lzma -d -- ".shellescape(tarfile,0)) + let tarfile = substitute(tarfile,'\.lzma','','e') +@@ -696,13 +696,13 @@ fun! tar#Extract() + echo "***note*** successfully extracted ".fname + endif + +- elseif filereadable(tarbase.".tzs") ++ elseif filereadable(tarbase.".tzst") + let extractcmd= substitute(extractcmd,"-","--zstd","") +-" call Decho("system(".extractcmd." ".shellescape(tarbase).".tzs ".shellescape(fname).")") +- call system(extractcmd." ".shellescape(tarbase).".txz ".shellescape(fname)) ++" call Decho("system(".extractcmd." ".shellescape(tarbase).".tzst ".shellescape(fname).")") ++ call system(extractcmd." ".shellescape(tarbase).".tzst ".shellescape(fname)) + if v:shell_error != 0 +- echohl Error | echo "***error*** ".extractcmd." ".tarbase.".tzs ".fname.": failed!" | echohl NONE +-" call Decho("***error*** ".extractcmd." ".tarbase.".tzs ".fname.": failed!") ++ echohl Error | echo "***error*** ".extractcmd." ".tarbase.".tzst ".fname.": failed!" | echohl NONE ++" call Decho("***error*** ".extractcmd." ".tarbase.".tzst ".fname.": failed!") + else + echo "***note*** successfully extracted ".fname + endif +@@ -710,7 +710,7 @@ fun! tar#Extract() + elseif filereadable(tarbase.".tar.zst") + let extractcmd= substitute(extractcmd,"-","--zstd","") + " call Decho("system(".extractcmd." ".shellescape(tarbase).".tar.zst ".shellescape(fname).")") +- call system(extractcmd." ".shellescape(tarbase).".tar.xz ".shellescape(fname)) ++ call system(extractcmd." ".shellescape(tarbase).".tar.zst ".shellescape(fname)) + if v:shell_error != 0 + echohl Error | echo "***error*** ".extractcmd." ".tarbase.".tar.zst ".fname.": failed!" | echohl NONE + " call Decho("***error*** ".extractcmd." ".tarbase.".tar.zst ".fname.": failed!") +diff --git a/runtime/plugin/tarPlugin.vim b/runtime/plugin/tarPlugin.vim +index d55492a93e33e..40d2242514d52 100644 +--- a/runtime/plugin/tarPlugin.vim ++++ b/runtime/plugin/tarPlugin.vim +@@ -45,7 +45,7 @@ augroup tar + au BufReadCmd *.tar.xz call tar#Browse(expand("")) + au BufReadCmd *.txz call tar#Browse(expand("")) + au BufReadCmd *.tar.zst call tar#Browse(expand("")) +- au BufReadCmd *.tzs call tar#Browse(expand("")) ++ au BufReadCmd *.tzst call tar#Browse(expand("")) + augroup END + com! -nargs=? -complete=file Vimuntar call tar#Vimuntar() + + + diff --git a/0014-update-tar_vim-to-support-permissions.patch b/0014-update-tar_vim-to-support-permissions.patch new file mode 100644 index 0000000000000000000000000000000000000000..1a7445594be6a69fe1baf7bcbd10b84906b99099 --- /dev/null +++ b/0014-update-tar_vim-to-support-permissions.patch @@ -0,0 +1,219 @@ +From 129a8446d23cd9cb4445fcfea259cba5e0487d29 Mon Sep 17 00:00:00 2001 +From: Lennart00 <73488709+Lennart00@users.noreply.github.com> +Date: Mon, 11 Nov 2024 22:39:30 +0100 +Subject: [PATCH] runtime(tar): Update tar.vim to support permissions + +These changes enable tar.vim to keep permissions of files that were +edited intact instead of replacing them with the default permissions. + +The major change for this is switching from "tar -OPxf", which reads out +the contents of the selected file from an tar archive to stdout to +"tar -pPxf" which extracts the selected file to the current directory +with permissions intact + +This requirs the temporary directory to be created earlier. + +closes: #7379 + +Signed-off-by: Lennart00 <73488709+Lennart00@users.noreply.github.com> +Signed-off-by: Christian Brabandt +--- + runtime/autoload/tar.vim | 104 +++++++++++++++++++++++---------------- + 1 file changed, 62 insertions(+), 42 deletions(-) + +diff --git a/runtime/autoload/tar.vim b/runtime/autoload/tar.vim +index 9c4f16d7f60a65..436e24eb67496d 100644 +--- a/runtime/autoload/tar.vim ++++ b/runtime/autoload/tar.vim +@@ -1,6 +1,6 @@ + " tar.vim: Handles browsing tarfiles + " AUTOLOAD PORTION +-" Date: Nov 11, 2023 ++" Date: Nov 11, 2024 + " Version: 32b (with modifications from the Vim Project) + " Maintainer: Charles E Campbell + " License: Vim License (see vim's :help license) +@@ -22,7 +22,7 @@ + if &cp || exists("g:loaded_tar") + finish + endif +-let g:loaded_tar= "v32a" ++let g:loaded_tar= "v32b" + if v:version < 702 + echohl WarningMsg + echo "***warning*** this version of tar needs vim 7.2" +@@ -40,7 +40,7 @@ if !exists("g:tar_browseoptions") + let g:tar_browseoptions= "Ptf" + endif + if !exists("g:tar_readoptions") +- let g:tar_readoptions= "OPxf" ++ let g:tar_readoptions= "pPxf" + endif + if !exists("g:tar_cmd") + let g:tar_cmd= "tar" +@@ -79,7 +79,7 @@ if !exists("g:tar_copycmd") + let g:tar_copycmd= g:netrw_localcopycmd + endif + if !exists("g:tar_extractcmd") +- let g:tar_extractcmd= "tar -xf" ++ let g:tar_extractcmd= "tar -pxf" + endif + + " set up shell quoting character +@@ -293,6 +293,41 @@ fun! tar#Read(fname,mode) + set report=10 + let tarfile = substitute(a:fname,'tarfile:\(.\{-}\)::.*$','\1','') + let fname = substitute(a:fname,'tarfile:.\{-}::\(.*\)$','\1','') ++ ++" changing the directory to the temporary earlier to allow tar to extract the file with permissions intact ++ if !exists("*mkdir") ++ redraw! ++ echohl Error | echo "***error*** (tar#Write) sorry, mkdir() doesn't work on your system" | echohl None ++ let &report= repkeep ++ return ++ endif ++ ++ let curdir= getcwd() ++ let tmpdir= tempname() ++ let b:curdir= tmpdir ++ let b:tmpdir= curdir ++ if tmpdir =~ '\.' ++ let tmpdir= substitute(tmpdir,'\.[^.]*$','','e') ++ endif ++ call mkdir(tmpdir,"p") ++ ++ " attempt to change to the indicated directory ++ try ++ exe "cd ".fnameescape(tmpdir) ++ catch /^Vim\%((\a\+)\)\=:E344/ ++ redraw! ++ echohl Error | echo "***error*** (tar#Write) cannot cd to temporary directory" | Echohl None ++ let &report= repkeep ++ return ++ endtry ++ ++ " place temporary files under .../_ZIPVIM_/ ++ if isdirectory("_ZIPVIM_") ++ call s:Rmdir("_ZIPVIM_") ++ endif ++ call mkdir("_ZIPVIM_") ++ cd _ZIPVIM_ ++ + if has("win32unix") && executable("cygpath") + " assuming cygwin + let tarfile=substitute(system("cygpath -u ".shellescape(tarfile,0)),'\n$','','e') +@@ -331,9 +366,11 @@ fun! tar#Read(fname,mode) + + 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 "read ".fname + 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 "read ".fname + elseif tarfile =~# '\(\.tgz\|\.tbz\|\.txz\)' + if has("unix") && executable("file") + let filekind= system("file ".shellescape(tarfile,1)) +@@ -342,20 +379,27 @@ fun! tar#Read(fname,mode) + 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 "read ".fname + 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 "read ".fname + 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 "read ".fname + else + exe "sil! r! gzip -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp ++ exe "read ".fname + 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 "read ".fname + 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 "read ".fname + 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 "read ".fname + else + if tarfile =~ '^\s*-' + " A file name starting with a dash is taken as an option. Prepend ./ to avoid that. +@@ -363,6 +407,16 @@ fun! tar#Read(fname,mode) + 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 ++ exe "read ".fname ++ endif ++ ++ redraw! ++ ++if v:shell_error != 0 ++ cd .. ++ call s:Rmdir("_ZIPVIM_") ++ exe "cd ".fnameescape(curdir) ++ echohl Error | echo "***error*** (tar#Read) sorry, unable to open or extract ".tarfile." with ".fname | echohl None + endif + + if doro +@@ -388,6 +442,10 @@ fun! tar#Write(fname) + let repkeep= &report + set report=10 + ++ " temporary buffer variable workaround because too fucking tired. but it works now ++ let curdir= b:curdir ++ let tmpdir= b:tmpdir ++ + if !exists("g:tar_secure") && a:fname =~ '^\s*-\|\s\+-' + redraw! + echohl WarningMsg | echo '***warning*** (tar#Write) rejecting tarfile member<'.a:fname.'> because of embedded "-"' +@@ -403,44 +461,6 @@ fun! tar#Write(fname) + " call Dret("tar#Write") + return + endif +- if !exists("*mkdir") +- redraw! +-" call Decho("***error*** (tar#Write) sorry, mkdir() doesn't work on your system") +- echohl Error | echo "***error*** (tar#Write) sorry, mkdir() doesn't work on your system" | echohl None +- let &report= repkeep +-" call Dret("tar#Write") +- return +- endif +- +- let curdir= getcwd() +- let tmpdir= tempname() +-" call Decho("orig tempname<".tmpdir.">") +- if tmpdir =~ '\.' +- let tmpdir= substitute(tmpdir,'\.[^.]*$','','e') +- endif +-" call Decho("tmpdir<".tmpdir.">") +- call mkdir(tmpdir,"p") +- +- " attempt to change to the indicated directory +- try +- exe "cd ".fnameescape(tmpdir) +- catch /^Vim\%((\a\+)\)\=:E344/ +- redraw! +-" call Decho("***error*** (tar#Write) cannot cd to temporary directory") +- echohl Error | echo "***error*** (tar#Write) cannot cd to temporary directory" | Echohl None +- let &report= repkeep +-" call Dret("tar#Write") +- return +- endtry +-" call Decho("current directory now: ".getcwd()) +- +- " place temporary files under .../_ZIPVIM_/ +- if isdirectory("_ZIPVIM_") +- call s:Rmdir("_ZIPVIM_") +- endif +- call mkdir("_ZIPVIM_") +- cd _ZIPVIM_ +-" call Decho("current directory now: ".getcwd()) + + let tarfile = substitute(b:tarfile,'tarfile:\(.\{-}\)::.*$','\1','') + let fname = substitute(b:tarfile,'tarfile:.\{-}::\(.*\)$','\1','') + + diff --git a/0015-fix-code-execution-with-tar_vim.patch b/0015-fix-code-execution-with-tar_vim.patch new file mode 100644 index 0000000000000000000000000000000000000000..642c5108e8c32b51d80307f8551fea11342b0eed --- /dev/null +++ b/0015-fix-code-execution-with-tar_vim.patch @@ -0,0 +1,91 @@ +From 334a13bff78aa0ad206bc436885f63e3a0bab399 Mon Sep 17 00:00:00 2001 +From: Christian Brabandt +Date: Sun, 2 Mar 2025 19:33:51 +0100 +Subject: [PATCH] patch 9.1.1164: [security]: code execution with tar.vim and + special crafted tar files + +Problem: editing a special crafted tar file allows code execution + (RyotaK, after 129a8446d23cd9cb4445fcfea259cba5e0487d29) +Solution: escape the filename before feeding it to the `:read` command + +Github Advisory: +https://github.com/vim/vim/security/advisories/GHSA-wfmf-8626-q3r3 + +Signed-off-by: Christian Brabandt +--- + runtime/autoload/tar.vim | 22 ++++++++++++---------- + 1 file changed, 12 insertions(+), 10 deletions(-) + +diff --git a/runtime/autoload/tar.vim b/runtime/autoload/tar.vim +index 1c2ed78c1907b..14e68b7899c72 100644 +--- a/runtime/autoload/tar.vim ++++ b/runtime/autoload/tar.vim +@@ -293,6 +293,8 @@ fun! tar#Read(fname,mode) + set report=10 + let tarfile = substitute(a:fname,'tarfile:\(.\{-}\)::.*$','\1','') + let fname = substitute(a:fname,'tarfile:.\{-}::\(.*\)$','\1','') ++ " be careful not to execute special crafted files ++ let escape_file = fname->fnameescape() + + " changing the directory to the temporary earlier to allow tar to extract the file with permissions intact + if !exists("*mkdir") +@@ -366,11 +368,11 @@ fun! tar#Read(fname,mode) + + 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 "read ".fname ++ exe "read ".escape_file + 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 "read ".fname ++ exe "read ".escape_file + elseif tarfile =~# '\(\.tgz\|\.tbz\|\.txz\)' + if has("unix") && executable("file") + let filekind= system("file ".shellescape(tarfile,1)) +@@ -379,27 +381,27 @@ fun! tar#Read(fname,mode) + 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 "read ".fname ++ exe "read ".escape_file + 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 "read ".fname ++ exe "read ".escape_file + 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 "read ".fname ++ exe "read ".escape_file + else + exe "sil! r! gzip -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp +- exe "read ".fname ++ exe "read ".escape_file + 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 "read ".fname ++ exe "read ".escape_file + 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 "read ".fname ++ exe "read ".escape_file + 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 "read ".fname ++ exe "read ".escape_file + else + if tarfile =~ '^\s*-' + " A file name starting with a dash is taken as an option. Prepend ./ to avoid that. +@@ -407,7 +409,7 @@ fun! tar#Read(fname,mode) + 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 +- exe "read ".fname ++ exe "read ".escape_file + endif + + redraw! + + diff --git a/0016-fix-CVE-2025-53905.patch b/0016-fix-CVE-2025-53905.patch new file mode 100644 index 0000000000000000000000000000000000000000..7ddeb4f45a998fd2a243a98e0f21723aaabc91bc --- /dev/null +++ b/0016-fix-CVE-2025-53905.patch @@ -0,0 +1,549 @@ +From 8f26b3cd15591f0474ee75064c100d35284580da Mon Sep 17 00:00:00 2001 +From: Christian Brabandt +Date: Tue, 15 Jul 2025 21:54:00 +0200 +Subject: [PATCH] patch 9.1.1552: [security]: path traversal issue in tar.vim + +--- + runtime/autoload/tar.vim | 245 ++++++++++++++++----------------------- + 1 file changed, 102 insertions(+), 143 deletions(-) + +diff --git a/runtime/autoload/tar.vim b/runtime/autoload/tar.vim +index e7b2738..6a7b21c 100644 +--- a/runtime/autoload/tar.vim ++++ b/runtime/autoload/tar.vim +@@ -23,9 +23,9 @@ if &cp || exists("g:loaded_tar") + finish + endif + let g:loaded_tar= "v32b" +-if v:version < 702 ++if v:version < 900 + echohl WarningMsg +- echo "***warning*** this version of tar needs vim 7.2" ++ echo "***warning*** this version of tar needs vim 9.0" + echohl Normal + finish + endif +@@ -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= "pPxf" ++ let g:tar_readoptions= "pxf" + 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,10 +99,26 @@ 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 + " ---------------- + ++" --------------------------------------------------------------------- ++" s:Msg: {{{2 ++fun! s:Msg(func, severity, msg) ++ redraw! ++ if a:severity =~? 'error' ++ echohl Error ++ else ++ echohl WarningMsg ++ endif ++ echo $"***{a:severity}*** ({a:func}) {a:msg}" ++ echohl None ++endfunc ++ + " --------------------------------------------------------------------- + " tar#Browse: {{{2 + fun! tar#Browse(tarfile) +@@ -111,9 +128,7 @@ fun! tar#Browse(tarfile) + + " sanity checks + if !executable(g:tar_cmd) +- redraw! +-" call Decho('***error*** (tar#Browse) "'.g:tar_cmd.'" not available on your system') +- echohl Error | echo '***error*** (tar#Browse) "'.g:tar_cmd.'" not available on your system' ++ call s:Msg('tar#Browse', 'error', $"{g:tar_cmd} not available on your system") + let &report= repkeep + " call Dret("tar#Browse") + return +@@ -122,9 +137,7 @@ fun! tar#Browse(tarfile) + " call Decho('a:tarfile<'.a:tarfile.'> not filereadable') + if a:tarfile !~# '^\a\+://' + " if it's an url, don't complain, let url-handlers such as vim do its thing +- redraw! +-" call Decho("***error*** (tar#Browse) File not readable<".a:tarfile.">") +- echohl Error | echo "***error*** (tar#Browse) File not readable<".a:tarfile.">" | echohl None ++ call s:Msg('tar#Browse', 'error', $"File not readable<{a:tarfile}>") + endif + let &report= repkeep + " call Dret("tar#Browse : file<".a:tarfile."> not readable") +@@ -203,29 +216,18 @@ fun! tar#Browse(tarfile) + exe "sil! r! ".g:tar_cmd." -".g:tar_browseoptions." ".shellescape(tarfile,1) + endif + if v:shell_error != 0 +- redraw! +- echohl WarningMsg | echo "***warning*** (tar#Browse) please check your g:tar_browseoptions<".g:tar_browseoptions.">" +-" call Dret("tar#Browse : a:tarfile<".a:tarfile.">") ++ call s:Msg('tar#Browse', 'warning', $"please check your g:tar_browseoptions '<{g:tar_browseoptions}>'") + return + endif +- " +- " FIXME:is this actually necessary? In case of an error, we should probably +- " have noticed in the if statement above since tar should have exited +- " with a non-zero exit code. +- " if line("$") == curlast || ( line("$") == (curlast + 1) && +- " \ getline("$") =~# '\c\<\%(warning\|error\|inappropriate\|unrecognized\)\>' && +- " \ getline("$") =~ '\s' ) +- " redraw! +- " echohl WarningMsg | echo "***warning*** (tar#Browse) ".a:tarfile." doesn't appear to be a tar file" | echohl None +- " keepj sil! %d +- " let eikeep= &ei +- " set ei=BufReadCmd,FileReadCmd +- " exe "r ".fnameescape(a:tarfile) +- " let &ei= eikeep +- " keepj sil! 1d +- " call Dret("tar#Browse : a:tarfile<".a: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 +@@ -246,14 +248,7 @@ fun! s:TarBrowseSelect() + let repkeep= &report + set report=10 + 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 =~ '^"' +@@ -276,7 +271,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).'")' +@@ -287,27 +283,19 @@ endfun + + " --------------------------------------------------------------------- + " tar#Read: {{{2 +-fun! tar#Read(fname,mode) ++fun! tar#Read(fname) + " call Dfunc("tar#Read(fname<".a:fname.">,mode=".a:mode.")") + let repkeep= &report + set report=10 + let tarfile = substitute(a:fname,'tarfile:\(.\{-}\)::.*$','\1','') + let fname = substitute(a:fname,'tarfile:.\{-}::\(.*\)$','\1','') + " be careful not to execute special crafted files +- let escape_file = fname->fnameescape() +- +-" changing the directory to the temporary earlier to allow tar to extract the file with permissions intact +- if !exists("*mkdir") +- redraw! +- echohl Error | echo "***error*** (tar#Write) sorry, mkdir() doesn't work on your system" | echohl None +- let &report= repkeep +- return +- endif ++ let escape_file = fname->substitute(g:tar_leading_pat, '', '')->fnameescape() + + let curdir= getcwd() ++ let b:curdir= curdir + let tmpdir= tempname() +- let b:curdir= tmpdir +- let b:tmpdir= curdir ++ let b:tmpdir= tmpdir + if tmpdir =~ '\.' + let tmpdir= substitute(tmpdir,'\.[^.]*$','','e') + endif +@@ -317,8 +305,7 @@ fun! tar#Read(fname,mode) + try + exe "cd ".fnameescape(tmpdir) + catch /^Vim\%((\a\+)\)\=:E344/ +- redraw! +- echohl Error | echo "***error*** (tar#Write) cannot cd to temporary directory" | Echohl None ++ call s:Msg('tar#Read', 'error', "cannot lcd to temporary directory") + let &report= repkeep + return + endtry +@@ -340,7 +327,7 @@ fun! tar#Read(fname,mode) + if fname =~ '\.bz2$' && executable("bzcat") + let decmp= "|bzcat" + let doro = 1 +- elseif fname =~ '\.t\=gz$' && executable("zcat") ++ elseif fname =~ '\.t\=gz$' && executable("zcat") + let decmp= "|zcat" + let doro = 1 + elseif fname =~ '\.lzma$' && executable("lzcat") +@@ -360,18 +347,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 + exe "read ".escape_file + 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 + exe "read ".escape_file + elseif tarfile =~# '\(\.tgz\|\.tbz\|\.txz\)' + if has("unix") && executable("file") +@@ -380,27 +360,27 @@ 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 + exe "read ".escape_file + 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 + exe "read ".escape_file + 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 + exe "read ".escape_file + 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 + exe "read ".escape_file + 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 + exe "read ".escape_file + 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 + exe "read ".escape_file + 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 + exe "read ".escape_file + else + if tarfile =~ '^\s*-' +@@ -408,17 +388,20 @@ fun! tar#Read(fname,mode) + 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 ++ exe "silent r! ".g:tar_cmd." -".g:tar_readoptions.shellescape(tarfile,1)." ".g:tar_secure.shellescape(fname,1).decmp + exe "read ".escape_file + endif ++ if get(b:, 'leading_slash', 0) ++ sil g/^tar: /d ++ endif + + redraw! + +-if v:shell_error != 0 ++ if v:shell_error != 0 + cd .. + call s:Rmdir("_ZIPVIM_") + exe "cd ".fnameescape(curdir) +- echohl Error | echo "***error*** (tar#Read) sorry, unable to open or extract ".tarfile." with ".fname | echohl None ++ call s:Msg('tar#Read', 'error', $"sorry, unable to open or extract {tarfile} with {fname}") + endif + + if doro +@@ -427,14 +410,14 @@ if v:shell_error != 0 + endif + + let b:tarfile= a:fname +- exe "file tarfile::".fnameescape(fname) + + " cleanup + keepj sil! 0d + set nomod + + let &report= repkeep +-" call Dret("tar#Read : b:tarfile<".b:tarfile.">") ++ exe "cd ".fnameescape(curdir) ++ silent exe "file tarfile::". fname->fnameescape() + endfun + + " --------------------------------------------------------------------- +@@ -448,13 +431,6 @@ fun! tar#Write(fname) + let curdir= b:curdir + let tmpdir= b:tmpdir + +- 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! +@@ -467,6 +443,26 @@ fun! tar#Write(fname) + let tarfile = substitute(b:tarfile,'tarfile:\(.\{-}\)::.*$','\1','') + let fname = substitute(b:tarfile,'tarfile:.\{-}::\(.*\)$','\1','') + ++ if get(b:, 'leading_slash', 0) ++ call s:Msg('tar#Write', 'error', $"sorry, not attempting to update {tarfile} with {fname}") ++ let &report= repkeep ++ return ++ endif ++ ++ if !isdirectory(fnameescape(tmpdir)) ++ call mkdir(fnameescape(tmpdir), 'p') ++ endif ++ exe $"lcd {fnameescape(tmpdir)}" ++ if isdirectory("_ZIPVIM_") ++ call s:Rmdir("_ZIPVIM_") ++ endif ++ call mkdir("_ZIPVIM_") ++ lcd _ZIPVIM_ ++ let dir = fnamemodify(fname, ':p:h') ++ if dir !~# '_ZIPVIM_$' ++ call mkdir(dir) ++ endif ++ + " handle compressed archives + if tarfile =~# '\.bz2' + call system("bzip2 -d -- ".shellescape(tarfile,0)) +@@ -502,9 +498,7 @@ fun! tar#Write(fname) + " call Decho("tarfile<".tarfile.">") + + if v:shell_error != 0 +- redraw! +-" call Decho("***error*** (tar#Write) sorry, unable to update ".tarfile." with ".fname) +- echohl Error | echo "***error*** (tar#Write) sorry, unable to update ".tarfile." with ".fname | echohl None ++ call s:Msg('tar#Write', 'error', $"sorry, unable to update {tarfile} with {fname}") + else + + " call Decho("tarfile<".tarfile."> fname<".fname.">") +@@ -525,32 +519,23 @@ 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)) ++ " Note: BSD tar does not support --delete flag ++ 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)) +- echohl Error | echo "***error*** (tar#Write) sorry, unable to update ".fnameescape(tarfile)." with ".fnameescape(fname) | echohl None ++ call s:Msg('tar#Write', 'error', $"sorry, unable to update {fnameescape(tarfile)} with {fnameescape(fname)} --delete not supported?") + 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)) ++ " update tarfile with new file ++ 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)) +- echohl Error | echo "***error*** (tar#Write) sorry, unable to update ".fnameescape(tarfile)." with ".fnameescape(fname) | echohl None ++ call s:Msg('tar#Write', 'error', $"sorry, unable to update {fnameescape(tarfile)} with {fnameescape(fname)}") + elseif exists("compress") + " call Decho("call system(".compress.")") + call system(compress) +@@ -581,7 +566,7 @@ fun! tar#Write(fname) + " cleanup and restore current directory + cd .. + call s:Rmdir("_ZIPVIM_") +- exe "cd ".fnameescape(curdir) ++ exe "cd ".fnameescape(pwdkeep) + setlocal nomod + + let &report= repkeep +@@ -596,6 +581,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 +@@ -622,13 +608,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 +@@ -646,19 +625,17 @@ fun! tar#Extract() + " call Decho("system(".extractcmd." ".shellescape(tarbase).".tar ".shellescape(fname).")") + call system(extractcmd." ".shellescape(tarbase).".tar ".shellescape(fname)) + if v:shell_error != 0 +- echohl Error | echo "***error*** ".extractcmd." ".tarbase.".tar ".fname.": failed!" | echohl NONE +-" call Decho("***error*** ".extractcmd." ".tarbase.".tar ".fname.": failed!") ++ call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarbase}.tar {fname}: failed!") + else +- echo "***note*** successfully extracted ".fname ++ echo "***note*** successfully extracted ". fname + endif + + elseif filereadable(tarbase.".tgz") + let extractcmd= substitute(extractcmd,"-","-z","") +-" call Decho("system(".extractcmd." ".shellescape(tarbase).".tgz ".shellescape(fname).")") +- call system(extractcmd." ".shellescape(tarbase).".tgz ".shellescape(fname)) ++ " call Decho("system(".extractcmd." ".shellescape(tarbase).".tgz ".shellescape(fname).")") ++ call system(extractcmd." ".shellescape(tarbase).".tgz ".shellescape(fname)) + if v:shell_error != 0 +- echohl Error | echo "***error*** ".extractcmd." ".tarbase.".tgz ".fname.": failed!" | echohl NONE +-" call Decho("***error*** ".extractcmd."t ".tarbase.".tgz ".fname.": failed!") ++ call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarbase}.tgz {fname}: failed!") + else + echo "***note*** successfully extracted ".fname + endif +@@ -668,8 +645,7 @@ fun! tar#Extract() + " call Decho("system(".extractcmd." ".shellescape(tarbase).".tar.gz ".shellescape(fname).")") + call system(extractcmd." ".shellescape(tarbase).".tar.gz ".shellescape(fname)) + if v:shell_error != 0 +- echohl Error | echo "***error*** ".extractcmd." ".tarbase.".tar.gz ".fname.": failed!" | echohl NONE +-" call Decho("***error*** ".extractcmd." ".tarbase.".tar.gz ".fname.": failed!") ++ call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarbase}.tar.gz {fname}: failed!") + else + echo "***note*** successfully extracted ".fname + endif +@@ -679,8 +655,7 @@ fun! tar#Extract() + " call Decho("system(".extractcmd." ".shellescape(tarbase).".tbz ".shellescape(fname).")") + call system(extractcmd." ".shellescape(tarbase).".tbz ".shellescape(fname)) + if v:shell_error != 0 +- echohl Error | echo "***error*** ".extractcmd."j ".tarbase.".tbz ".fname.": failed!" | echohl NONE +-" call Decho("***error*** ".extractcmd."j ".tarbase.".tbz ".fname.": failed!") ++ call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarbase}.tbz {fname}: failed!") + else + echo "***note*** successfully extracted ".fname + endif +@@ -690,8 +665,7 @@ fun! tar#Extract() + " call Decho("system(".extractcmd." ".shellescape(tarbase).".tar.bz2 ".shellescape(fname).")") + call system(extractcmd." ".shellescape(tarbase).".tar.bz2 ".shellescape(fname)) + if v:shell_error != 0 +- echohl Error | echo "***error*** ".extractcmd."j ".tarbase.".tar.bz2 ".fname.": failed!" | echohl NONE +-" call Decho("***error*** ".extractcmd."j ".tarbase.".tar.bz2 ".fname.": failed!") ++ call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarbase}.tar.bz2 {fname}: failed!") + else + echo "***note*** successfully extracted ".fname + endif +@@ -701,8 +675,7 @@ fun! tar#Extract() + " call Decho("system(".extractcmd." ".shellescape(tarbase).".txz ".shellescape(fname).")") + call system(extractcmd." ".shellescape(tarbase).".txz ".shellescape(fname)) + if v:shell_error != 0 +- echohl Error | echo "***error*** ".extractcmd." ".tarbase.".txz ".fname.": failed!" | echohl NONE +-" call Decho("***error*** ".extractcmd." ".tarbase.".txz ".fname.": failed!") ++ call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarbase}.txz {fname}: failed!") + else + echo "***note*** successfully extracted ".fname + endif +@@ -712,8 +685,7 @@ fun! tar#Extract() + " call Decho("system(".extractcmd." ".shellescape(tarbase).".tar.xz ".shellescape(fname).")") + call system(extractcmd." ".shellescape(tarbase).".tar.xz ".shellescape(fname)) + if v:shell_error != 0 +- echohl Error | echo "***error*** ".extractcmd." ".tarbase.".tar.xz ".fname.": failed!" | echohl NONE +-" call Decho("***error*** ".extractcmd." ".tarbase.".tar.xz ".fname.": failed!") ++ call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarbase}.tar.xz {fname}: failed!") + else + echo "***note*** successfully extracted ".fname + endif +@@ -723,8 +695,7 @@ fun! tar#Extract() + " call Decho("system(".extractcmd." ".shellescape(tarbase).".tzst ".shellescape(fname).")") + call system(extractcmd." ".shellescape(tarbase).".tzst ".shellescape(fname)) + if v:shell_error != 0 +- echohl Error | echo "***error*** ".extractcmd." ".tarbase.".tzst ".fname.": failed!" | echohl NONE +-" call Decho("***error*** ".extractcmd." ".tarbase.".tzst ".fname.": failed!") ++ call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarbase}.tzst {fname}: failed!") + else + echo "***note*** successfully extracted ".fname + endif +@@ -734,8 +705,7 @@ fun! tar#Extract() + " call Decho("system(".extractcmd." ".shellescape(tarbase).".tar.zst ".shellescape(fname).")") + call system(extractcmd." ".shellescape(tarbase).".tar.zst ".shellescape(fname)) + if v:shell_error != 0 +- echohl Error | echo "***error*** ".extractcmd." ".tarbase.".tar.zst ".fname.": failed!" | echohl NONE +-" call Decho("***error*** ".extractcmd." ".tarbase.".tar.zst ".fname.": failed!") ++ call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarbase}.tar.zst {fname}: failed!") + else + echo "***note*** successfully extracted ".fname + endif +@@ -750,17 +720,6 @@ endfun + " --------------------------------------------------------------------- + " s:Rmdir: {{{2 + fun! s:Rmdir(fname) +-" call Dfunc("Rmdir(fname<".a:fname.">)") +- if has("unix") +- call system("/bin/rm -rf -- ".shellescape(a:fname,0)) +- elseif has("win32") || has("win95") || has("win64") || has("win16") +- if &shell =~? "sh$" +- call system("/bin/rm -rf -- ".shellescape(a:fname,0)) +- else +- call system("del /S ".shellescape(a:fname,0)) +- endif +- endif +-" call Dret("Rmdir") + endfun + + " --------------------------------------------------------------------- +-- +2.43.5 + diff --git a/vim.spec b/vim.spec index 84e64924cb7e29f07a2b4e5c5960223202c990e5..007d133a0b1a380216f862e2fd751d3afa2a2d71 100644 --- a/vim.spec +++ b/vim.spec @@ -1,4 +1,4 @@ -%define anolis_release 6 +%define anolis_release 7 %bcond_without gui %bcond_with default_editor @@ -65,7 +65,17 @@ Patch0006: 0006-fix-CVE-2023-48236.patch Patch0007: 0007-fix-CVE-2023-48237.patch Patch0008: 0008-fix-CVE-2023-48706.patch # https://github.com/vim/vim/commit/322ba9108612bead5eb7731ccb66763dec69ef1b -Patch0010: 0009-fix-CVE-2024-43802.patch +Patch0009: 0009-fix-CVE-2024-43802.patch +# https://github.com/vim/vim/commit/51b62387be93c65fa56bbabe1c3 +Patch0010: 0010-fix-CVE-2024-47814.patch +# https://github.com/vim/vim/commit/586294a04179d855c3d1d4ee5ea83931963680b8 +Patch0011: 0011-fix-CVE-2025-53906.patch +Patch0012: 0012-comment-out-strange-error-condition-check.patch +Patch0013: 0013-fix-a-few-problems-with-the-tar-plugin.patch +Patch0014: 0014-update-tar_vim-to-support-permissions.patch +Patch0015: 0015-fix-code-execution-with-tar_vim.patch +# https://github.com/vim/vim/commit/87757c6b0a4b2c1f71c72ea8e1438b8fb116b239 +Patch0016: 0016-fix-CVE-2025-53905.patch Patch1001: 1001-vim-8.0-copy-paste.patch #CVE-2024-22667 @@ -819,6 +829,9 @@ touch %{buildroot}/%{data_dir}/vimfiles/doc/tags %endif %changelog +* Thu Jul 31 2025 zjl002254423 -3:9.0.2092-7 +- Add patch to fix CVE-2025-53905,CVE-2025-53906,CVE-2024-41957,CVE-2024-41965,CVE-2024-47814 + * Mon Jul 07 2025 wenxin - 3:9.0.2092-6 - Add patch to Fix CVE-2024-43802, CVE-2024-43374