diff --git a/backport-CVE-2023-4733.patch b/backport-CVE-2023-4733.patch new file mode 100644 index 0000000000000000000000000000000000000000..3066ede0a0f7442fddd747d0f9874696683760b0 --- /dev/null +++ b/backport-CVE-2023-4733.patch @@ -0,0 +1,43 @@ +From e1dc9a627536304bc4f738c21e909ad9fcf3974c Mon Sep 17 00:00:00 2001 +From: Christian Brabandt +Date: Sat, 2 Sep 2023 14:40:13 +0200 +Subject: [PATCH 13/52] patch 9.0.1840: [security] use-after-free in do_ecmd + +Problem: use-after-free in do_ecmd +Solution: Verify oldwin pointer after reset_VIsual() + +Signed-off-by: Christian Brabandt +--- + src/ex_cmds.c | 14 ++++++++++---- + 1 files changed, 10 insertions(+), 4 deletions(-) + +diff --git a/src/ex_cmds.c b/src/ex_cmds.c +index 20d4d9a2e..9348b4edd 100644 +--- a/src/ex_cmds.c ++++ b/src/ex_cmds.c +@@ -2603,12 +2603,18 @@ do_ecmd( + goto theend; + } + +- /* +- * End Visual mode before switching to another buffer, so the text can be +- * copied into the GUI selection buffer. +- */ ++ ++ // End Visual mode before switching to another buffer, so the text can be ++ // copied into the GUI selection buffer. ++ // Careful: may trigger ModeChanged() autocommand ++ ++ // Should we block autocommands here? + reset_VIsual(); + ++ // autocommands freed window :( ++ if (oldwin != NULL && !win_valid(oldwin)) ++ oldwin = NULL; ++ + #if defined(FEAT_EVAL) + if ((command != NULL || newlnum > (linenr_T)0) + && *get_vim_var_str(VV_SWAPCOMMAND) == NUL) +-- +2.33.0 + diff --git a/backport-CVE-2023-4734.patch b/backport-CVE-2023-4734.patch new file mode 100644 index 0000000000000000000000000000000000000000..cfcfcfc7d4df75c573cfabab58cd0a3feda398e4 --- /dev/null +++ b/backport-CVE-2023-4734.patch @@ -0,0 +1,44 @@ +From 4c6fe2e2ea62469642ed1d80b16d39e616b25cf5 Mon Sep 17 00:00:00 2001 +From: Christian Brabandt +Date: Sat, 2 Sep 2023 19:30:03 +0200 +Subject: [PATCH 21/52] patch 9.0.1846: [security] crash in fullcommand + +Problem: crash in fullcommand +Solution: Check for typeval correctly + +Signed-off-by: Christian Brabandt +--- + src/ex_docmd.c | 2 +- + src/testdir/test_functions.vim | 5 +++++ + 2 files changed, 6 insertions(+), 1 deletion(-) + +diff --git a/src/ex_docmd.c b/src/ex_docmd.c +index 32d52ab21..10d979d49 100644 +--- a/src/ex_docmd.c ++++ b/src/ex_docmd.c +@@ -4047,7 +4047,7 @@ f_fullcommand(typval_T *argvars, typval_T *rettv) + || check_for_opt_bool_arg(argvars, 1) == FAIL)) + return; + +- name = argvars[0].vval.v_string; ++ name = tv_get_string(&argvars[0]); + if (name == NULL) + return; + +diff --git a/src/testdir/test_functions.vim b/src/testdir/test_functions.vim +index 0eda5de38..ab1dbf3b5 100644 +--- a/src/testdir/test_functions.vim ++++ b/src/testdir/test_functions.vim +@@ -2962,4 +2962,9 @@ func Test_virtcol() + bwipe! + endfunc + ++func Test_fullcommand() ++ " this used to crash vim ++ call assert_equal('', fullcommand(10)) ++endfunc ++ + " vim: shiftwidth=2 sts=2 expandtab +-- +2.33.0 + diff --git a/backport-CVE-2023-4735.patch b/backport-CVE-2023-4735.patch new file mode 100644 index 0000000000000000000000000000000000000000..95a4d7411fdb4632bb00aecd9761a2d60924d30c --- /dev/null +++ b/backport-CVE-2023-4735.patch @@ -0,0 +1,30 @@ +From 889f6af37164775192e33b233a90e86fd3df0f57 Mon Sep 17 00:00:00 2001 +From: Christian Brabandt +Date: Sat, 2 Sep 2023 19:43:33 +0200 +Subject: [PATCH 22/52] patch 9.0.1847: [security] potential oob write in + do_addsub() + +Problem: potential oob write in do_addsub() +Solution: don't overflow buf2, check size in for loop() + +Signed-off-by: Christian Brabandt +--- + src/ops.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletion(-) + +diff --git a/src/ops.c b/src/ops.c +index d46a049fe..f4524d3d7 100644 +--- a/src/ops.c ++++ b/src/ops.c +@@ -2848,7 +2848,7 @@ do_addsub( + for (bit = bits; bit > 0; bit--) + if ((n >> (bit - 1)) & 0x1) break; + +- for (i = 0; bit > 0; bit--) ++ for (i = 0; bit > 0 && i < (NUMBUFLEN - 1); bit--) + buf2[i++] = ((n >> (bit - 1)) & 0x1) ? '1' : '0'; + + buf2[i] = '\0'; +-- +2.33.0 + diff --git a/backport-CVE-2023-4736.patch b/backport-CVE-2023-4736.patch new file mode 100644 index 0000000000000000000000000000000000000000..3439d1db2ac38d6f87b3dd37f3690b0a84055c38 --- /dev/null +++ b/backport-CVE-2023-4736.patch @@ -0,0 +1,167 @@ +From 816fbcc262687b81fc46f82f7bbeb1453addfe0c Mon Sep 17 00:00:00 2001 +From: Christian Brabandt +Date: Thu, 31 Aug 2023 23:52:30 +0200 +Subject: [PATCH] patch 9.0.1833: [security] runtime file fixes + +Problem: runtime files may execute code in current dir +Solution: only execute, if not run from current directory + +The perl, zig and ruby filetype plugins and the zip and gzip autoload +plugins may try to load malicious executable files from the current +working directory. This is especially a problem on windows, where the +current directory is implicitly in your $PATH and windows may even run a +file with the extension `.bat` because of $PATHEXT. + +So make sure that we are not trying to execute a file from the current +directory. If this would be the case, error out (for the zip and gzip) +plugins or silently do not run those commands (for the ftplugins). + +This assumes, that only the current working directory is bad. For all +other directories, it is assumed that those directories were +intentionally set to the $PATH by the user. + +Signed-off-by: Christian Brabandt +--- + runtime/autoload/gzip.vim | 7 +++- + runtime/autoload/zip.vim | 4 +++ + runtime/ftplugin/perl.vim | 3 +- + runtime/ftplugin/ruby.vim | 68 ++++++++++++++++++++++----------------- + 4 files changed, 51 insertions(+), 31 deletions(-) + +diff --git a/runtime/autoload/gzip.vim b/runtime/autoload/gzip.vim +index 95dd9067945af..ac9e37bf85e7e 100644 +--- a/runtime/autoload/gzip.vim ++++ b/runtime/autoload/gzip.vim +@@ -9,12 +9,17 @@ + fun s:check(cmd) + let name = substitute(a:cmd, '\(\S*\).*', '\1', '') + if !exists("s:have_" . name) ++ " safety check, don't execute anything from the current directory ++ let f = fnamemodify(exepath(name), ":p:h") !=# getcwd() ++ if !f ++ echoerr "Warning: NOT executing " .. name .. " from current directory!" ++ endif + let e = executable(name) + if e < 0 + let r = system(name . " --version") + let e = (r !~ "not found" && r != "") + endif +- exe "let s:have_" . name . "=" . e ++ exe "let s:have_" . name . "=" . (e && f) + endif + exe "return s:have_" . name + endfun +diff --git a/runtime/autoload/zip.vim b/runtime/autoload/zip.vim +index 8dda30c418838..0331a542aca40 100644 +--- a/runtime/autoload/zip.vim ++++ b/runtime/autoload/zip.vim +@@ -57,6 +57,10 @@ if !exists("g:zip_extractcmd") + let g:zip_extractcmd= g:zip_unzipcmd + endif + ++if fnamemodify(exepath(g:zip_unzipcmd), ":p:h") ==# getcwd() ++ echoerr "Warning: NOT executing " .. g:zip_unzipcmd .. " from current directory!" ++ finish ++endif + " ---------------- + " Functions: {{{1 + " ---------------- +diff --git a/runtime/ftplugin/perl.vim b/runtime/ftplugin/perl.vim +index d0bdbc0cfb158..edc7b960f12f9 100644 +--- a/runtime/ftplugin/perl.vim ++++ b/runtime/ftplugin/perl.vim +@@ -54,7 +54,8 @@ endif + + " Set this once, globally. + if !exists("perlpath") +- if executable("perl") ++ " safety check: don't execute perl from current directory ++ if executable("perl") && fnamemodify(exepath("perl"), ":p:h") != getcwd() + try + if &shellxquote != '"' + let perlpath = system('perl -e "print join(q/,/,@INC)"') +diff --git a/runtime/ftplugin/ruby.vim b/runtime/ftplugin/ruby.vim +index 8c1f47731c351..f4e1f60438921 100644 +--- a/runtime/ftplugin/ruby.vim ++++ b/runtime/ftplugin/ruby.vim +@@ -99,41 +99,51 @@ function! s:build_path(path) abort + return path + endfunction + +-if !exists('b:ruby_version') && !exists('g:ruby_path') && isdirectory(expand('%:p:h')) +- let s:version_file = findfile('.ruby-version', '.;') +- if !empty(s:version_file) && filereadable(s:version_file) +- let b:ruby_version = get(readfile(s:version_file, '', 1), '') +- if !has_key(g:ruby_version_paths, b:ruby_version) +- let g:ruby_version_paths[b:ruby_version] = s:query_path(fnamemodify(s:version_file, ':p:h')) ++let s:execute_ruby = 1 ++" Security Check, don't execute ruby from the current directory ++if fnamemodify(exepath("ruby"), ":p:h") ==# getcwd() ++ let s:execute_ruby = 0 ++endif ++ ++function SetRubyPath() ++ if !exists('b:ruby_version') && !exists('g:ruby_path') && isdirectory(expand('%:p:h')) ++ let s:version_file = findfile('.ruby-version', '.;') ++ if !empty(s:version_file) && filereadable(s:version_file) && s:execute_ruby ++ let b:ruby_version = get(readfile(s:version_file, '', 1), '') ++ if !has_key(g:ruby_version_paths, b:ruby_version) ++ let g:ruby_version_paths[b:ruby_version] = s:query_path(fnamemodify(s:version_file, ':p:h')) ++ endif + endif + endif +-endif + +-if exists("g:ruby_path") +- let s:ruby_path = type(g:ruby_path) == type([]) ? join(g:ruby_path, ',') : g:ruby_path +-elseif has_key(g:ruby_version_paths, get(b:, 'ruby_version', '')) +- let s:ruby_paths = g:ruby_version_paths[b:ruby_version] +- let s:ruby_path = s:build_path(s:ruby_paths) +-else +- if !exists('g:ruby_default_path') +- if has("ruby") && has("win32") +- ruby ::VIM::command( 'let g:ruby_default_path = split("%s",",")' % $:.join(%q{,}) ) +- elseif executable('ruby') && !empty($HOME) +- let g:ruby_default_path = s:query_path($HOME) +- else +- let g:ruby_default_path = map(split($RUBYLIB,':'), 'v:val ==# "." ? "" : v:val') ++ if exists("g:ruby_path") ++ let s:ruby_path = type(g:ruby_path) == type([]) ? join(g:ruby_path, ',') : g:ruby_path ++ elseif has_key(g:ruby_version_paths, get(b:, 'ruby_version', '')) && s:execute_ruby ++ let s:ruby_paths = g:ruby_version_paths[b:ruby_version] ++ let s:ruby_path = s:build_path(s:ruby_paths) ++ else ++ if !exists('g:ruby_default_path') ++ if has("ruby") && has("win32") ++ ruby ::VIM::command( 'let g:ruby_default_path = split("%s",",")' % $:.join(%q{,}) ) ++ elseif executable('ruby') && !empty($HOME) && s:execute_ruby ++ let g:ruby_default_path = s:query_path($HOME) ++ else ++ let g:ruby_default_path = map(split($RUBYLIB,':'), 'v:val ==# "." ? "" : v:val') ++ endif + endif ++ let s:ruby_paths = g:ruby_default_path ++ let s:ruby_path = s:build_path(s:ruby_paths) + endif +- let s:ruby_paths = g:ruby_default_path +- let s:ruby_path = s:build_path(s:ruby_paths) +-endif + +-if stridx(&l:path, s:ruby_path) == -1 +- let &l:path = s:ruby_path +-endif +-if exists('s:ruby_paths') && stridx(&l:tags, join(map(copy(s:ruby_paths),'v:val."/tags"'),',')) == -1 +- let &l:tags = &tags . ',' . join(map(copy(s:ruby_paths),'v:val."/tags"'),',') +-endif ++ if stridx(&l:path, s:ruby_path) == -1 ++ let &l:path = s:ruby_path ++ endif ++ if exists('s:ruby_paths') && stridx(&l:tags, join(map(copy(s:ruby_paths),'v:val."/tags"'),',')) == -1 ++ let &l:tags = &tags . ',' . join(map(copy(s:ruby_paths),'v:val."/tags"'),',') ++ endif ++endfunction ++ ++call SetRubyPath() + + if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter") + let b:browsefilter = "Ruby Source Files (*.rb)\t*.rb\n" . diff --git a/backport-patch-9.0.0473-fullcommand-only-works-for-the-current-script-version.patch b/backport-patch-9.0.0473-fullcommand-only-works-for-the-current-script-version.patch new file mode 100644 index 0000000000000000000000000000000000000000..aba6fe6086c2b6cb88d7d249eac762671299a44a --- /dev/null +++ b/backport-patch-9.0.0473-fullcommand-only-works-for-the-current-script-version.patch @@ -0,0 +1,156 @@ +From aa5341477c9f3840d63f709de3b9e5d0266f93d7 Mon Sep 17 00:00:00 2001 +From: Bram Moolenaar +Date: Thu, 15 Sep 2022 21:46:02 +0100 +Subject: [PATCH] patch 9.0.0473: fullcommand() only works for the current + script version + +Problem: fullcommand() only works for the current script version. +Solution: Add an optional argument for the script version. +--- + runtime/doc/builtin.txt | 14 ++++++++++---- + src/ex_docmd.c | 30 +++++++++++++++++++++++------- + src/testdir/test_cmdline.vim | 3 +++ + src/testdir/test_vim9_builtin.vim | 7 +++++++ + 4 files changed, 43 insertions(+), 11 deletions(-) + +diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt +index fb8b116010095..53179ca85aba6 100644 +--- a/runtime/doc/builtin.txt ++++ b/runtime/doc/builtin.txt +@@ -195,7 +195,7 @@ foldlevel({lnum}) Number fold level at {lnum} + foldtext() String line displayed for closed fold + foldtextresult({lnum}) String text for closed fold at {lnum} + foreground() Number bring the Vim window to the foreground +-fullcommand({name}) String get full command from {name} ++fullcommand({name} [, {vim9}]) String get full command from {name} + funcref({name} [, {arglist}] [, {dict}]) + Funcref reference to function {name} + function({name} [, {arglist}] [, {dict}]) +@@ -2954,14 +2954,20 @@ foreground() Move the Vim window to the foreground. Useful when sent from + {only in the Win32, Motif and GTK GUI versions and the + Win32 console version} + +-fullcommand({name}) *fullcommand()* ++fullcommand({name} [, {vim9}]) *fullcommand()* + Get the full command name from a short abbreviated command + name; see |20.2| for details on command abbreviations. + + The string argument {name} may start with a `:` and can + include a [range], these are skipped and not returned. +- Returns an empty string if a command doesn't exist or if it's +- ambiguous (for user-defined commands). ++ Returns an empty string if a command doesn't exist, if it's ++ ambiguous (for user-defined commands) or cannot be shortened ++ this way. |vim9-no-shorten| ++ ++ Without the {vim9} argument uses the current script version. ++ If {vim9} is present and FALSE then legacy script rules are ++ used. When {vim9} is present and TRUE then Vim9 rules are ++ used, e.g. "en" is not a short form of "endif". + + For example `fullcommand('s')`, `fullcommand('sub')`, + `fullcommand(':%substitute')` all return "substitute". +diff --git a/src/ex_docmd.c b/src/ex_docmd.c +index 0e5e1db5ecd87..814f1b6f8a5a8 100644 +--- a/src/ex_docmd.c ++++ b/src/ex_docmd.c +@@ -4033,20 +4033,31 @@ cmd_exists(char_u *name) + void + f_fullcommand(typval_T *argvars, typval_T *rettv) + { +- exarg_T ea; +- char_u *name; +- char_u *p; ++ exarg_T ea; ++ char_u *name; ++ char_u *p; ++ int vim9script = in_vim9script(); ++ int save_cmod_flags = cmdmod.cmod_flags; + + rettv->v_type = VAR_STRING; + rettv->vval.v_string = NULL; + +- if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL) ++ if (in_vim9script() ++ && (check_for_string_arg(argvars, 0) == FAIL ++ || check_for_opt_bool_arg(argvars, 1) == FAIL)) + return; + + name = argvars[0].vval.v_string; + if (name == NULL) + return; + ++ if (argvars[1].v_type != VAR_UNKNOWN) ++ { ++ vim9script = tv_get_bool(&argvars[1]); ++ cmdmod.cmod_flags &= ~(CMOD_VIM9CMD | CMOD_LEGACY); ++ cmdmod.cmod_flags |= vim9script ? CMOD_VIM9CMD : CMOD_LEGACY; ++ } ++ + while (*name == ':') + name++; + name = skip_range(name, TRUE, NULL); +@@ -4054,10 +4065,13 @@ f_fullcommand(typval_T *argvars, typval_T *rettv) + ea.cmd = (*name == '2' || *name == '3') ? name + 1 : name; + ea.cmdidx = (cmdidx_T)0; + ea.addr_count = 0; ++ ++emsg_silent; // don't complain about using "en" in Vim9 script + p = find_ex_command(&ea, NULL, NULL, NULL); ++ --emsg_silent; + if (p == NULL || ea.cmdidx == CMD_SIZE) +- return; +- if (in_vim9script()) ++ goto theend; ++ ++ if (vim9script) + { + int res; + +@@ -4066,12 +4080,14 @@ f_fullcommand(typval_T *argvars, typval_T *rettv) + --emsg_silent; + + if (res == FAIL) +- return; ++ goto theend; + } + + rettv->vval.v_string = vim_strsave(IS_USER_CMDIDX(ea.cmdidx) + ? get_user_command_name(ea.useridx, ea.cmdidx) + : cmdnames[ea.cmdidx].cmd_name); ++theend: ++ cmdmod.cmod_flags = save_cmod_flags; + } + #endif + +diff --git a/src/testdir/test_cmdline.vim b/src/testdir/test_cmdline.vim +index 7febc12269953..27ca8bf841b5c 100644 +--- a/src/testdir/test_cmdline.vim ++++ b/src/testdir/test_cmdline.vim +@@ -648,6 +648,9 @@ func Test_fullcommand() + \ '3match': 'match', + \ 'aboveleft': 'aboveleft', + \ 'abo': 'aboveleft', ++ \ 'en': 'endif', ++ \ 'end': 'endif', ++ \ 'endi': 'endif', + \ 's': 'substitute', + \ '5s': 'substitute', + \ ':5s': 'substitute', +diff --git a/src/testdir/test_vim9_builtin.vim b/src/testdir/test_vim9_builtin.vim +index 109cb35af6877..dccd99bb321ca 100644 +--- a/src/testdir/test_vim9_builtin.vim ++++ b/src/testdir/test_vim9_builtin.vim +@@ -1529,6 +1529,13 @@ def Test_fullcommand() + assert_equal('scriptnames', fullcommand('scr')) + assert_equal('', fullcommand('scg')) + fullcommand('')->assert_equal('') ++ ++ assert_equal('', fullcommand('en')) ++ legacy call assert_equal('endif', fullcommand('en')) ++ assert_equal('endif', fullcommand('en', 0)) ++ legacy call assert_equal('endif', fullcommand('en', 0)) ++ assert_equal('', fullcommand('en', 1)) ++ legacy call assert_equal('', fullcommand('en', 1)) + enddef + + def Test_funcref() diff --git a/backport-patch-9.0.0474-fullcommand-testfailure.patch b/backport-patch-9.0.0474-fullcommand-testfailure.patch new file mode 100644 index 0000000000000000000000000000000000000000..a9aad6427fe5ea423189c553a7d078d3788105e7 --- /dev/null +++ b/backport-patch-9.0.0474-fullcommand-testfailure.patch @@ -0,0 +1,24 @@ +From dd44b58f64a173ffc976cc96ccdd00cd5493b273 Mon Sep 17 00:00:00 2001 +From: Bram Moolenaar +Date: Thu, 15 Sep 2022 22:03:57 +0100 +Subject: [PATCH] patch 9.0.0474: fullcommand() test failure + +Problem: fullcommand() test failure. +Solution: Update function table. +--- + src/evalfunc.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletion(-) + +diff --git a/src/evalfunc.c b/src/evalfunc.c +index cd315629498b0..cab3213469954 100644 +--- a/src/evalfunc.c ++++ b/src/evalfunc.c +@@ -1848,7 +1848,7 @@ static funcentry_T global_functions[] = + ret_string, f_foldtextresult}, + {"foreground", 0, 0, 0, NULL, + ret_void, f_foreground}, +- {"fullcommand", 1, 1, FEARG_1, arg1_string, ++ {"fullcommand", 1, 2, FEARG_1, arg2_string_bool, + ret_string, f_fullcommand}, + {"funcref", 1, 3, FEARG_1, arg3_any_list_dict, + ret_func_unknown, f_funcref}, diff --git a/vim.spec b/vim.spec index 4f379df707a7eafa1ea3c91d9e4a960727666a5a..5c79138b5efd894d065578fbd8cd2428a6b6e7c3 100644 --- a/vim.spec +++ b/vim.spec @@ -12,7 +12,7 @@ Name: vim Epoch: 2 Version: 9.0 -Release: 14 +Release: 15 Summary: Vim is a highly configurable text editor for efficiently creating and changing any kind of text. License: Vim and MIT URL: http://www.vim.org @@ -96,6 +96,12 @@ Patch6066: backport-vim-7.0-rclocation.patch Patch6067: backport-CVE-2023-2426.patch Patch6068: backport-CVE-2023-2609.patch Patch6069: backport-CVE-2023-2610.patch +Patch6070: backport-CVE-2023-4736.patch +Patch6071: backport-CVE-2023-4733.patch +Patch6072: backport-patch-9.0.0473-fullcommand-only-works-for-the-current-script-version.patch +Patch6073: backport-patch-9.0.0474-fullcommand-testfailure.patch +Patch6074: backport-CVE-2023-4734.patch +Patch6075: backport-CVE-2023-4735.patch Patch9000: bugfix-rm-modify-info-version.patch @@ -503,6 +509,12 @@ LC_ALL=en_US.UTF-8 make -j1 test %{_mandir}/man1/evim.* %changelog +* Thu Sep 07 2023 wangjiang - 2:9.0-15 +- Type:CVE +- ID:CVE-2023-4736 CVE-2023-4733 CVE-2023-4734 CVE-2023-4735 +- SUG:NA +- DESC:fix CVE-2023-4736 CVE-2023-4733 CVE-2023-4734 CVE-2023-4735 + * Sat May 13 2023 wangjiang - 2:9.0-14 - Type:CVE - ID:CVE-2023-2609 CVE-2023-2610