From 74937538ada600dc48b9ff868996e4340d39c90d Mon Sep 17 00:00:00 2001 From: gc-taifu Date: Mon, 3 Mar 2025 11:29:30 +0800 Subject: [PATCH] Fix CVEs regression --- 0001-fix-CVE-2023-48231.patch | 81 ++++++++++ 0002-fix-CVE-2023-48232.patch | 66 ++++++++ 0003-fix-CVE-2023-48233.patch | 115 +++++++++++++ 0004-fix-CVE-2023-48234.patch | 53 ++++++ 0005-fix-CVE-2023-48235.patch | 52 ++++++ 0006-fix-CVE-2023-48236.patch | 56 +++++++ 0007-fix-CVE-2023-48237.patch | 100 ++++++++++++ 0008-fix-CVE-2023-48706.patch | 296 ++++++++++++++++++++++++++++++++++ vim.spec | 23 ++- 9 files changed, 837 insertions(+), 5 deletions(-) create mode 100644 0001-fix-CVE-2023-48231.patch create mode 100644 0002-fix-CVE-2023-48232.patch create mode 100644 0003-fix-CVE-2023-48233.patch create mode 100644 0004-fix-CVE-2023-48234.patch create mode 100644 0005-fix-CVE-2023-48235.patch create mode 100644 0006-fix-CVE-2023-48236.patch create mode 100644 0007-fix-CVE-2023-48237.patch create mode 100644 0008-fix-CVE-2023-48706.patch diff --git a/0001-fix-CVE-2023-48231.patch b/0001-fix-CVE-2023-48231.patch new file mode 100644 index 0000000..3ceb585 --- /dev/null +++ b/0001-fix-CVE-2023-48231.patch @@ -0,0 +1,81 @@ +From 25aabc2b8ee1e19ced6f4da9d866cf9378fc4c5a Mon Sep 17 00:00:00 2001 +From: Christian Brabandt +Date: Tue, 14 Nov 2023 19:31:34 +0100 +Subject: [PATCH] patch 9.0.2106: [security]: Use-after-free in win_close() + +Problem: [security]: Use-after-free in win_close() +Solution: Check window is valid, before accessing it + +If the current window structure is no longer valid (because a previous +autocommand has already freed this window), fail and return before +attempting to set win->w_closing variable. + +Add a test to trigger ASAN in CI + +Signed-off-by: Christian Brabandt +--- + src/testdir/test_crash.vim | 33 +++++++++++++++++++++++++++++++++ + src/window.c | 2 ++ + 2 files changed, 37 insertions(+) + create mode 100644 src/testdir/crash/poc1 + +diff --git a/src/testdir/test_crash.vim b/src/testdir/test_crash.vim +index 5cd07e2a3..b093b053c 100644 +--- a/src/testdir/test_crash.vim ++++ b/src/testdir/test_crash.vim +@@ -110,6 +110,39 @@ func Test_crash1() + call delete('X_crash1_result.txt') + endfunc + ++func Test_crash1_2() ++ CheckNotBSD ++ CheckExecutable dash ++ ++ " The following used to crash Vim ++ let opts = #{cmd: 'sh'} ++ let vim = GetVimProg() ++ let result = 'X_crash1_1_result.txt' ++ ++ let buf = RunVimInTerminal('sh', opts) ++ ++ let file = 'crash/poc1' ++ 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 1: [OK]" > '.. result .. "\") ++ call TermWait(buf, 150) ++ ++ " clean up ++ exe buf .. "bw!" ++ ++ exe "sp " .. result ++ ++ let expected = [ ++ \ 'crash 1: [OK]', ++ \ ] ++ ++ call assert_equal(expected, getline(1, '$')) ++ bw! ++ ++ call delete(result) ++endfunc ++ + func Test_crash2() + " The following used to crash Vim + let opts = #{wait_for_ruler: 0, rows: 20} +diff --git a/src/window.c b/src/window.c +index f77ede330..55ce31c88 100644 +--- a/src/window.c ++++ b/src/window.c +@@ -2682,6 +2682,8 @@ win_close(win_T *win, int free_buf) + reset_VIsual_and_resel(); // stop Visual mode + + other_buffer = TRUE; ++ if (!win_valid(win)) ++ return FAIL; + win->w_closing = TRUE; + apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, FALSE, curbuf); + if (!win_valid(win)) +-- +2.41.0 + diff --git a/0002-fix-CVE-2023-48232.patch b/0002-fix-CVE-2023-48232.patch new file mode 100644 index 0000000..249c6b2 --- /dev/null +++ b/0002-fix-CVE-2023-48232.patch @@ -0,0 +1,66 @@ +From cb0b99f0672d8446585d26e998343dceca17d1ce Mon Sep 17 00:00:00 2001 +From: Christian Brabandt +Date: Tue, 14 Nov 2023 20:05:59 +0100 +Subject: [PATCH] patch 9.0.2107: [security]: FPE in adjust_plines_for_skipcol + +Problem: [security]: FPE in adjust_plines_for_skipcol +Solution: don't divide by zero, return zero + +Prevent a floating point exception when calculating w_skipcol (which can +happen with a small window when the number option is set and cpo+=n). + +Add a test to verify + +Signed-off-by: Christian Brabandt +--- + src/move.c | 5 +++-- + src/testdir/test_scroll_opt.vim | 19 +++++++++++++++++++ + 2 files changed, 24 insertions(+), 2 deletions(-) + +diff --git a/src/move.c b/src/move.c +index ce06dc339..fbb352a32 100644 +--- a/src/move.c ++++ b/src/move.c +@@ -45,8 +45,9 @@ adjust_plines_for_skipcol(win_T *wp) + return 0; + + int width = wp->w_width - win_col_off(wp); +- if (wp->w_skipcol >= width) +- return (wp->w_skipcol - width) / (width + win_col_off2(wp)) + 1; ++ int w2 = width + win_col_off2(wp); ++ if (wp->w_skipcol >= width && w2 > 0) ++ return (wp->w_skipcol - width) / w2 + 1; + + return 0; + } +diff --git a/src/testdir/test_scroll_opt.vim b/src/testdir/test_scroll_opt.vim +index d5d08a24c..342d382c2 100644 +--- a/src/testdir/test_scroll_opt.vim ++++ b/src/testdir/test_scroll_opt.vim +@@ -926,4 +926,23 @@ func Test_smoothscroll_cursor_top() + call StopVimInTerminal(buf) + endfunc + ++" Division by zero, shouldn't crash ++func Test_smoothscroll_crash() ++ CheckScreendump ++ ++ let lines =<< trim END ++ 20 new ++ vsp ++ put =repeat('aaaa', 20) ++ set nu fdc=1 smoothscroll cpo+=n ++ vert resize 0 ++ exe "norm! 0\" ++ END ++ call writefile(lines, 'XSmoothScrollCrash', 'D') ++ let buf = RunVimInTerminal('-u NONE -S XSmoothScrollCrash', #{rows: 12, cols:40}) ++ call term_sendkeys(buf, "2\\") ++ ++ call StopVimInTerminal(buf) ++endfunc ++ + " vim: shiftwidth=2 sts=2 expandtab +-- +2.41.0 + diff --git a/0003-fix-CVE-2023-48233.patch b/0003-fix-CVE-2023-48233.patch new file mode 100644 index 0000000..efe78f7 --- /dev/null +++ b/0003-fix-CVE-2023-48233.patch @@ -0,0 +1,115 @@ +From ac63787734fda2e294e477af52b3bd601517fa78 Mon Sep 17 00:00:00 2001 +From: Christian Brabandt +Date: Tue, 14 Nov 2023 20:45:48 +0100 +Subject: [PATCH] patch 9.0.2108: [security]: overflow with count for :s + command + +Problem: [security]: overflow with count for :s command +Solution: Abort the :s command if the count is too large + +If the count after the :s command is larger than what fits into a +(signed) long variable, abort with e_value_too_large. + +Adds a test with INT_MAX as count and verify it correctly fails. + +It seems the return value on Windows using mingw compiler wraps around, +so the initial test using :s/./b/9999999999999999999999999990 doesn't +fail there, since the count is wrapping around several times and finally +is no longer larger than 2147483647. So let's just use 2147483647 in the +test, which hopefully will always cause a failure + +Signed-off-by: Christian Brabandt +--- + runtime/doc/change.txt | 8 ++++---- + runtime/doc/cmdline.txt | 3 ++- + runtime/doc/tags | 1 + + src/ex_cmds.c | 7 +++++++ + src/testdir/test_substitute.vim | 1 + + 5 files changed, 17 insertions(+), 5 deletions(-) + +diff --git a/runtime/doc/change.txt b/runtime/doc/change.txt +index 65da9a7c6..dccaa44c8 100644 +--- a/runtime/doc/change.txt ++++ b/runtime/doc/change.txt +@@ -1,4 +1,4 @@ +-*change.txt* For Vim version 9.0. Last change: 2023 Sep 19 ++*change.txt* For Vim version 9.0. Last change: 2023 Nov 15 + + + VIM REFERENCE MANUAL by Bram Moolenaar +@@ -644,9 +644,9 @@ For other systems the tmpnam() library function is used. + current line only. When [count] is given, replace in + [count] lines, starting with the last line in [range]. + When [range] is omitted start in the current line. +- *E939* +- [count] must be a positive number. Also see +- |cmdline-ranges|. ++ *E939* *E1510* ++ [count] must be a positive number (max 2147483647) ++ Also see |cmdline-ranges|. + + See |:s_flags| for [flags]. + The delimiter doesn't need to be /, see +diff --git a/runtime/doc/cmdline.txt b/runtime/doc/cmdline.txt +index c5d0096dd..cbcf0ad27 100644 +--- a/runtime/doc/cmdline.txt ++++ b/runtime/doc/cmdline.txt +@@ -1,4 +1,4 @@ +-*cmdline.txt* For Vim version 9.0. Last change: 2023 May 20 ++*cmdline.txt* For Vim version 9.0. Last change: 2023 Nov 15 + + + VIM REFERENCE MANUAL by Bram Moolenaar +@@ -362,6 +362,7 @@ terminals) + A positive number represents the absolute index of an entry + as it is given in the first column of a :history listing. + This number remains fixed even if other entries are deleted. ++ (see |E1510|) + + A negative number means the relative position of an entry, + counted from the newest entry (which has index -1) backwards. +diff --git a/runtime/doc/tags b/runtime/doc/tags +index f49061aa2..0021ddb12 100644 +--- a/runtime/doc/tags ++++ b/runtime/doc/tags +@@ -4514,6 +4514,7 @@ E1507 builtin.txt /*E1507* + E1508 editing.txt /*E1508* + E1509 editing.txt /*E1509* + E151 helphelp.txt /*E151* ++E1510 change.txt /*E1510* + E152 helphelp.txt /*E152* + E153 helphelp.txt /*E153* + E154 helphelp.txt /*E154* +diff --git a/src/ex_cmds.c b/src/ex_cmds.c +index 3544092d6..c5f912e7e 100644 +--- a/src/ex_cmds.c ++++ b/src/ex_cmds.c +@@ -3993,6 +3993,13 @@ ex_substitute(exarg_T *eap) + emsg(_(e_positive_count_required)); + return; + } ++ else if (i >= INT_MAX) ++ { ++ char buf[20]; ++ vim_snprintf(buf, sizeof(buf), "%ld", i); ++ semsg(_(e_val_too_large), buf); ++ return; ++ } + eap->line1 = eap->line2; + eap->line2 += i - 1; + if (eap->line2 > curbuf->b_ml.ml_line_count) +diff --git a/src/testdir/test_substitute.vim b/src/testdir/test_substitute.vim +index b99d0e005..3ed159799 100644 +--- a/src/testdir/test_substitute.vim ++++ b/src/testdir/test_substitute.vim +@@ -206,6 +206,7 @@ func Test_substitute_count() + call assert_equal(['foo foo', 'foo foo', 'foo foo', 'bar foo', 'bar foo'], + \ getline(1, '$')) + ++ call assert_fails('s/./b/2147483647', 'E1510:') + bwipe! + endfunc + +-- +2.41.0 + diff --git a/0004-fix-CVE-2023-48234.patch b/0004-fix-CVE-2023-48234.patch new file mode 100644 index 0000000..92fa196 --- /dev/null +++ b/0004-fix-CVE-2023-48234.patch @@ -0,0 +1,53 @@ +From 58f9befca1fa172068effad7f2ea5a9d6a7b0cca Mon Sep 17 00:00:00 2001 +From: Christian Brabandt +Date: Tue, 14 Nov 2023 21:02:30 +0100 +Subject: [PATCH] patch 9.0.2109: [security]: overflow in nv_z_get_count + +Problem: [security]: overflow in nv_z_get_count +Solution: break out, if count is too large + +When getting the count for a normal z command, it may overflow for large +counts given. So verify, that we can safely store the result in a long. + +Signed-off-by: Christian Brabandt +--- + src/normal.c | 7 +++++++ + src/testdir/test_normal.vim | 5 +++++ + 2 files changed, 14 insertions(+) + +diff --git a/src/normal.c b/src/normal.c +index a06d61e6f..16b4b4506 100644 +--- a/src/normal.c ++++ b/src/normal.c +@@ -2562,7 +2562,14 @@ nv_z_get_count(cmdarg_T *cap, int *nchar_arg) + if (nchar == K_DEL || nchar == K_KDEL) + n /= 10; + else if (VIM_ISDIGIT(nchar)) ++ { ++ if (n > LONG_MAX / 10) ++ { ++ clearopbeep(cap->oap); ++ break; ++ } + n = n * 10 + (nchar - '0'); ++ } + else if (nchar == CAR) + { + #ifdef FEAT_GUI +diff --git a/src/testdir/test_normal.vim b/src/testdir/test_normal.vim +index c7d37f066..6b889f46b 100644 +--- a/src/testdir/test_normal.vim ++++ b/src/testdir/test_normal.vim +@@ -4159,4 +4159,9 @@ func Test_normal33_g_cmd_nonblank() + bw! + endfunc + ++func Test_normal34_zet_large() ++ " shouldn't cause overflow ++ norm! z9765405999999999999 ++endfunc ++ + " vim: shiftwidth=2 sts=2 expandtab +-- +2.41.0 + diff --git a/0005-fix-CVE-2023-48235.patch b/0005-fix-CVE-2023-48235.patch new file mode 100644 index 0000000..ec74bf4 --- /dev/null +++ b/0005-fix-CVE-2023-48235.patch @@ -0,0 +1,52 @@ +From 060623e4a3bc72b011e7cd92bedb3bfb64e06200 Mon Sep 17 00:00:00 2001 +From: Christian Brabandt +Date: Tue, 14 Nov 2023 21:33:29 +0100 +Subject: [PATCH] patch 9.0.2110: [security]: overflow in ex address parsing + +Problem: [security]: overflow in ex address parsing +Solution: Verify that lnum is positive, before substracting from + LONG_MAX + +[security]: overflow in ex address parsing + +When parsing relative ex addresses one may unintentionally cause an +overflow (because LONG_MAX - lnum will overflow for negative addresses). + +So verify that lnum is actually positive before doing the overflow +check. + +Signed-off-by: Christian Brabandt +--- + src/ex_docmd.c | 2 +- + src/testdir/test_excmd.vim | 4 ++++ + 2 files changed, 7 insertions(+), 1 deletion(-) + +diff --git a/src/ex_docmd.c b/src/ex_docmd.c +index 06837ac92..01d411a63 100644 +--- a/src/ex_docmd.c ++++ b/src/ex_docmd.c +@@ -4644,7 +4644,7 @@ get_address( + lnum -= n; + else + { +- if (n >= LONG_MAX - lnum) ++ if (lnum >= 0 && n >= LONG_MAX - lnum) + { + emsg(_(e_line_number_out_of_range)); + goto error; +diff --git a/src/testdir/test_excmd.vim b/src/testdir/test_excmd.vim +index 3637351f6..47fc26726 100644 +--- a/src/testdir/test_excmd.vim ++++ b/src/testdir/test_excmd.vim +@@ -724,5 +724,9 @@ func Test_write_after_rename() + bwipe! + endfunc + ++" catch address lines overflow ++func Test_ex_address_range_overflow() ++ call assert_fails(':--+foobar', 'E492:') ++endfunc + + " vim: shiftwidth=2 sts=2 expandtab +2.41.0 + diff --git a/0006-fix-CVE-2023-48236.patch b/0006-fix-CVE-2023-48236.patch new file mode 100644 index 0000000..51c6916 --- /dev/null +++ b/0006-fix-CVE-2023-48236.patch @@ -0,0 +1,56 @@ +From 73b2d3790cad5694fc0ed0db2926e4220c48d968 Mon Sep 17 00:00:00 2001 +From: Christian Brabandt +Date: Tue, 14 Nov 2023 21:58:26 +0100 +Subject: [PATCH] patch 9.0.2111: [security]: overflow in get_number + +Problem: [security]: overflow in get_number +Solution: Return 0 when the count gets too large + +[security]: overflow in get_number + +When using the z= command, we may overflow the count with values larger +than MAX_INT. So verify that we do not overflow and in case when an +overflow is detected, simply return 0 + +Signed-off-by: Christian Brabandt +--- + src/misc1.c | 2 ++ + src/testdir/test_spell.vim | 9 +++++++++ + 2 files changed, 13 insertions(+) + +diff --git a/src/misc1.c b/src/misc1.c +index 5b008c614..5f9828ebe 100644 +--- a/src/misc1.c ++++ b/src/misc1.c +@@ -975,6 +975,8 @@ get_number( + c = safe_vgetc(); + if (VIM_ISDIGIT(c)) + { ++ if (n > INT_MAX / 10) ++ return 0; + n = n * 10 + c - '0'; + msg_putchar(c); + ++typed; +diff --git a/src/testdir/test_spell.vim b/src/testdir/test_spell.vim +index be0bc5581..1ddcd83d5 100644 +--- a/src/testdir/test_spell.vim ++++ b/src/testdir/test_spell.vim +@@ -1077,6 +1077,15 @@ func Test_spell_compatible() + call StopVimInTerminal(buf) + endfunc + ++func Test_z_equal_with_large_count() ++ split ++ set spell ++ call setline(1, "ff") ++ norm 0z=337203685477580 ++ set nospell ++ bwipe! ++endfunc ++ + let g:test_data_aff1 = [ + \"SET ISO8859-1", + \"TRY esianrtolcdugmphbyfvkwjkqxz-\xEB\xE9\xE8\xEA\xEF\xEE\xE4\xE0\xE2\xF6\xFC\xFB'ESIANRTOLCDUGMPHBYFVKWJKQXZ", +-- +2.41.0 + diff --git a/0007-fix-CVE-2023-48237.patch b/0007-fix-CVE-2023-48237.patch new file mode 100644 index 0000000..3a6f526 --- /dev/null +++ b/0007-fix-CVE-2023-48237.patch @@ -0,0 +1,100 @@ +From 6bf131888a3d1de62bbfa8a7ea03c0ddccfd496e Mon Sep 17 00:00:00 2001 +From: Christian Brabandt +Date: Tue, 14 Nov 2023 22:42:59 +0100 +Subject: [PATCH] patch 9.0.2112: [security]: overflow in shift_line + +Problem: [security]: overflow in shift_line +Solution: allow a max indent of INT_MAX + +[security]: overflow in shift_line + +When shifting lines in operator pending mode and using a very large +value, we may overflow the size of integer. Fix this by using a long +variable, testing if the result would be larger than INT_MAX and if so, +indent by INT_MAX value. + +Special case: We cannot use long here, since on 32bit architectures (or +on Windows?), it typically cannot take larger values than a plain int, +so we have to use long long count, decide whether the resulting +multiplication of the shiftwidth value * amount is larger than INT_MAX +and if so, we will store INT_MAX as possible larges value in the long +long count variable. + +Then we can safely cast it back to int when calling the functions to set +the indent (set_indent() or change_indent()). So this should be safe. + +Add a test that when using a huge value in operator pending mode for +shifting, we will shift by INT_MAX + +closes: #13535 + +Signed-off-by: Christian Brabandt +--- + src/ops.c | 15 ++++++++++----- + src/testdir/test_indent.vim | 11 +++++++++++ + 2 files changed, 23 insertions(+), 5 deletions(-) + +diff --git a/src/ops.c b/src/ops.c +index c0a2981d6..ecd7fc217 100644 +--- a/src/ops.c ++++ b/src/ops.c +@@ -229,11 +229,11 @@ shift_line( + int amount, + int call_changed_bytes) // call changed_bytes() + { +- int count; ++ long long count; + int i, j; + int sw_val = (int)get_sw_value_indent(curbuf); + +- count = get_indent(); // get current indent ++ count = (long long)get_indent(); // get current indent + + if (round) // round off indent + { +@@ -260,14 +260,19 @@ shift_line( + count = 0; + } + else +- count += sw_val * amount; ++ { ++ if ((long long)sw_val * (long long)amount > INT_MAX - count) ++ count = INT_MAX; ++ else ++ count += (long long)sw_val * (long long)amount; ++ } + } + + // Set new indent + if (State & VREPLACE_FLAG) +- change_indent(INDENT_SET, count, FALSE, NUL, call_changed_bytes); ++ change_indent(INDENT_SET, (int)count, FALSE, NUL, call_changed_bytes); + else +- (void)set_indent(count, call_changed_bytes ? SIN_CHANGED : 0); ++ (void)set_indent((int)count, call_changed_bytes ? SIN_CHANGED : 0); + } + + /* +diff --git a/src/testdir/test_indent.vim b/src/testdir/test_indent.vim +index 96e9d2300..217a7ae62 100644 +--- a/src/testdir/test_indent.vim ++++ b/src/testdir/test_indent.vim +@@ -275,4 +275,15 @@ func Test_formatting_keeps_first_line_indent() + bwipe! + endfunc + ++" Test for indenting with large amount, causes overflow ++func Test_indent_overflow_count() ++ new ++ setl sw=8 ++ call setline(1, "abc") ++ norm! V2147483647> ++ " indents by INT_MAX ++ call assert_equal(2147483647, indent(1)) ++ close! ++endfunc ++ + " vim: shiftwidth=2 sts=2 expandtab +-- +2.41.0 + diff --git a/0008-fix-CVE-2023-48706.patch b/0008-fix-CVE-2023-48706.patch new file mode 100644 index 0000000..9c55c40 --- /dev/null +++ b/0008-fix-CVE-2023-48706.patch @@ -0,0 +1,296 @@ +From 26c11c56888d01e298cd8044caf860f3c26f57bb Mon Sep 17 00:00:00 2001 +From: Christian Brabandt +Date: Wed, 22 Nov 2023 21:26:41 +0100 +Subject: [PATCH] patch 9.0.2121: [security]: use-after-free in ex_substitute + +Problem: [security]: use-after-free in ex_substitute +Solution: always allocate memory + +closes: #13552 + +A recursive :substitute command could cause a heap-use-after free in Vim +(CVE-2023-48706). + +The whole reproducible test is a bit tricky, I can only reproduce this +reliably when no previous substitution command has been used yet +(which is the reason, the test needs to run as first one in the +test_substitute.vim file) and as a combination of the `:~` command +together with a :s command that contains the special substitution atom `~\=` +which will make use of a sub-replace special atom and calls a vim script +function. + +There was a comment in the existing :s code, that already makes the +`sub` variable allocate memory so that a recursive :s call won't be able +to cause any issues here, so this was known as a potential problem +already. But for the current test-case that one does not work, because +the substitution does not start with `\=` but with `~\=` (and since +there does not yet exist a previous substitution atom, Vim will simply +increment the `sub` pointer (which then was not allocated dynamically) +and later one happily use a sub-replace special expression (which could +then free the `sub` var). + +The following commit fixes this, by making the sub var always using +allocated memory, which also means we need to free the pointer whenever +we leave the function. Since sub is now always an allocated variable, +we also do no longer need the sub_copy variable anymore, since this one +was used to indicated when sub pointed to allocated memory (and had +therefore to be freed on exit) and when not. + +Github Security Advisory: +https://github.com/vim/vim/security/advisories/GHSA-c8qm-x72m-q53q + +Signed-off-by: Christian Brabandt +--- + src/ex_cmds.c | 50 ++++++++++++++++++++++++--------- + src/testdir/test_substitute.vim | 48 +++++++++++++++++++++++++++++-- + 2 files changed, 85 insertions(+), 15 deletions(-) + +diff --git a/src/ex_cmds.c b/src/ex_cmds.c +index c5f912e7e..a08682b07 100644 +--- a/src/ex_cmds.c ++++ b/src/ex_cmds.c +@@ -3737,13 +3737,13 @@ ex_substitute(exarg_T *eap) + int save_do_all; // remember user specified 'g' flag + int save_do_ask; // remember user specified 'c' flag + char_u *pat = NULL, *sub = NULL; // init for GCC +- char_u *sub_copy = NULL; + int delimiter; + int sublen; + int got_quit = FALSE; + int got_match = FALSE; + int which_pat; + char_u *cmd; ++ char_u *p; + int save_State; + linenr_T first_line = 0; // first changed line + linenr_T last_line= 0; // below last changed line AFTER the +@@ -3827,8 +3827,12 @@ ex_substitute(exarg_T *eap) + * Small incompatibility: vi sees '\n' as end of the command, but in + * Vim we want to use '\n' to find/substitute a NUL. + */ +- sub = cmd; // remember the start of the substitution ++ p = cmd; // remember the start of the substitution + cmd = skip_substitute(cmd, delimiter); ++ sub = vim_strsave(p); ++ if (sub == NULL) ++ // out of memory ++ return; + + if (!eap->skip) + { +@@ -3839,14 +3843,22 @@ ex_substitute(exarg_T *eap) + if (old_sub == NULL) // there is no previous command + { + emsg(_(e_no_previous_substitute_regular_expression)); ++ vim_free(sub); + return; + } +- sub = old_sub; ++ vim_free(sub); ++ sub = vim_strsave(old_sub); ++ if (sub == NULL) ++ // out of memory ++ return; + } + else + { + vim_free(old_sub); + old_sub = vim_strsave(sub); ++ if (old_sub == NULL) ++ // out of memory ++ return; + } + } + } +@@ -3858,7 +3870,7 @@ ex_substitute(exarg_T *eap) + return; + } + pat = NULL; // search_regcomp() will use previous pattern +- sub = old_sub; ++ sub = vim_strsave(old_sub); + + // Vi compatibility quirk: repeating with ":s" keeps the cursor in the + // last column after using "$". +@@ -3877,7 +3889,10 @@ ex_substitute(exarg_T *eap) + linenr_T joined_lines_count; + + if (eap->skip) ++ { ++ vim_free(sub); + return; ++ } + curwin->w_cursor.lnum = eap->line1; + if (*cmd == 'l') + eap->flags = EXFLAG_LIST; +@@ -3904,6 +3919,7 @@ ex_substitute(exarg_T *eap) + save_re_pat(RE_SUBST, pat, magic_isset()); + // put pattern in history + add_to_history(HIST_SEARCH, pat, TRUE, NUL); ++ vim_free(sub); + + return; + } +@@ -3991,6 +4007,7 @@ ex_substitute(exarg_T *eap) + if (i <= 0 && !eap->skip && subflags.do_error) + { + emsg(_(e_positive_count_required)); ++ vim_free(sub); + return; + } + else if (i >= INT_MAX) +@@ -3998,6 +4015,7 @@ ex_substitute(exarg_T *eap) + char buf[20]; + vim_snprintf(buf, sizeof(buf), "%ld", i); + semsg(_(e_val_too_large), buf); ++ vim_free(sub); + return; + } + eap->line1 = eap->line2; +@@ -4016,17 +4034,22 @@ ex_substitute(exarg_T *eap) + if (eap->nextcmd == NULL) + { + semsg(_(e_trailing_characters_str), cmd); ++ vim_free(sub); + return; + } + } + + if (eap->skip) // not executing commands, only parsing ++ { ++ vim_free(sub); + return; ++ } + + if (!subflags.do_count && !curbuf->b_p_ma) + { + // Substitution is not allowed in non-'modifiable' buffer + emsg(_(e_cannot_make_changes_modifiable_is_off)); ++ vim_free(sub); + return; + } + +@@ -4034,6 +4057,7 @@ ex_substitute(exarg_T *eap) + { + if (subflags.do_error) + emsg(_(e_invalid_command)); ++ vim_free(sub); + return; + } + +@@ -4054,20 +4078,20 @@ ex_substitute(exarg_T *eap) + */ + if (sub[0] == '\\' && sub[1] == '=') + { +- sub = vim_strsave(sub); +- if (sub == NULL) ++ p = vim_strsave(sub); ++ vim_free(sub); ++ if (p == NULL) + return; +- sub_copy = sub; ++ sub = p; + } + else + { +- char_u *newsub = regtilde(sub, magic_isset()); ++ p = regtilde(sub, magic_isset()); + +- if (newsub != sub) ++ if (p != sub) + { +- // newsub was allocated, free it later. +- sub_copy = newsub; +- sub = newsub; ++ vim_free(sub); ++ sub = p; + } + } + +@@ -4965,7 +4989,7 @@ outofmem: + #endif + + vim_regfree(regmatch.regprog); +- vim_free(sub_copy); ++ vim_free(sub); + + // Restore the flag values, they can be used for ":&&". + subflags.do_all = save_do_all; +diff --git a/src/testdir/test_substitute.vim b/src/testdir/test_substitute.vim +index 3ed159799..7c2bbb476 100644 +--- a/src/testdir/test_substitute.vim ++++ b/src/testdir/test_substitute.vim +@@ -4,6 +4,32 @@ source shared.vim + source check.vim + source screendump.vim + ++" NOTE: This needs to be the first test to be ++" run in the file, since it depends on ++" that the previous substitution atom ++" was not yet set. ++" ++" recursive call of :s and sub-replace special ++" (did cause heap-use-after free in < v9.0.2121) ++func Test_aaaa_substitute_expr_recursive_special() ++ func R() ++ " FIXME: leaving out the 'n' flag leaks memory, why? ++ %s/./\='.'/gn ++ endfunc ++ new Xfoobar_UAF ++ put ='abcdef' ++ let bufnr = bufnr('%') ++ try ++ silent! :s/./~\=R()/0 ++ "call assert_fails(':s/./~\=R()/0', 'E939:') ++ let @/='.' ++ ~g ++ catch /^Vim\%((\a\+)\)\=:E565:/ ++ endtry ++ delfunc R ++ exe bufnr .. "bw!" ++endfunc ++ + func Test_multiline_subst() + enew! + call append(0, ["1 aa", +@@ -147,7 +173,6 @@ func Test_substitute_repeat() + call feedkeys("Qsc\y", 'tx') + bwipe! + endfunc +- + " Test %s/\n// which is implemented as a special case to use a + " more efficient join rather than doing a regular substitution. + func Test_substitute_join() +@@ -1447,11 +1472,30 @@ func Test_substitute_expr_switch_win() + endfunc + new Xfoobar + let bufnr = bufnr('%') +- put ="abcdef" ++ put ='abcdef' + silent! s/\%')/\=R() + call assert_fails(':%s/./\=R()/g', 'E565:') + delfunc R + exe bufnr .. "bw!" + endfunc + ++" recursive call of :s using test-replace special ++func Test_substitute_expr_recursive() ++ func Q() ++ %s/./\='foobar'/gn ++ return "foobar" ++ endfunc ++ func R() ++ %s/./\=Q()/g ++ endfunc ++ new Xfoobar_UAF ++ let bufnr = bufnr('%') ++ put ='abcdef' ++ silent! s/./\=R()/g ++ call assert_fails(':%s/./\=R()/g', 'E565:') ++ delfunc R ++ delfunc Q ++ exe bufnr .. "bw!" ++endfunc ++ + " vim: shiftwidth=2 sts=2 expandtab +2.41.0 + diff --git a/vim.spec b/vim.spec index eedfe1f..5fa603f 100644 --- a/vim.spec +++ b/vim.spec @@ -1,4 +1,4 @@ -%define anolis_release 4 +%define anolis_release 5 %bcond_without gui %bcond_with default_editor @@ -55,13 +55,22 @@ Source11: vim-default-editor.fish Source12: view_wrapper Source13: vi_wrapper -Patch0001: 1001-vim-8.0-copy-paste.patch - +# CVE +Patch0001: 0001-fix-CVE-2023-48231.patch +Patch0002: 0002-fix-CVE-2023-48232.patch +Patch0003: 0003-fix-CVE-2023-48233.patch +Patch0004: 0004-fix-CVE-2023-48234.patch +Patch0005: 0005-fix-CVE-2023-48235.patch +Patch0006: 0006-fix-CVE-2023-48236.patch +Patch0007: 0007-fix-CVE-2023-48237.patch +Patch0008: 0008-fix-CVE-2023-48706.patch + +Patch1001: 1001-vim-8.0-copy-paste.patch #CVE-2024-22667 #https://github.com/vim/vim/commit/b39b240c386a5a29241415541f1c99e2e6b8ce47 -Patch0002: 1002-stack-buffer-overflow-in-option-callback-functions.patch +Patch1002: 1002-stack-buffer-overflow-in-option-callback-functions.patch #https://github.com/vim/vim/commit/9d1bed5eccdbb46a26b8a484f5e9163c40e63919 -Patch0003: 1003-fix-cve-2025-24014.patch +Patch1003: 1003-fix-cve-2025-24014.patch BuildRequires: autoconf gcc glibc-gconv-extra make BuildRequires: gettext gpm-devel libacl-devel @@ -806,6 +815,10 @@ touch %{buildroot}/%{data_dir}/vimfiles/doc/tags %endif %changelog +* Mon Mar 3 2025 Chang Gao - 3:9.0.2092-5 +- Fix cve regression: +- CVE-2023-48231~CVE-2023-48237 and CVE-2023-48706 + * Fri Feb 28 2025 yangxinyu - 3:9.0.2092-4 - fix fix CVE-2025-24014 -- Gitee