upgrade version to 9.0.2092

This commit is contained in:
wangjiang 2024-02-04 10:24:57 +08:00
parent e593e83967
commit 00bf74da9a
99 changed files with 31 additions and 7394 deletions

View File

@ -1,28 +0,0 @@
From d4566c14e71c55dcef05fb34ea94eba835831527 Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Sat, 24 Sep 2022 21:06:39 +0100
Subject: [PATCH] patch 9.0.0581: adding a character for incsearch fails at end
of line
Problem: Adding a character for incsearch fails at end of line.
Solution: Only check cursor line number.
---
src/move.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/move.c b/src/move.c
index 6c654ac..4123ca8 100644
--- a/src/move.c
+++ b/src/move.c
@@ -652,7 +652,7 @@ cursor_valid(void)
void
validate_cursor(void)
{
- check_cursor();
+ check_cursor_lnum();
check_cursor_moved(curwin);
if ((curwin->w_valid & (VALID_WCOL|VALID_WROW)) != (VALID_WCOL|VALID_WROW))
curs_columns(TRUE);
--
2.27.0

View File

@ -1,53 +0,0 @@
From 083692d598139228e101b8c521aaef7bcf256e9a Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Wed, 29 Jun 2022 21:16:58 +0100
Subject: [PATCH] patch 9.0.0009: going past the end of a menu item with only
modifier
Problem: Going past the end of a menu item with only modifier.
Solution: Check for NUL.
---
src/message.c | 4 ++--
src/testdir/test_menu.vim | 13 +++++++++++++
2 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/src/message.c b/src/message.c
index 02380e9..becb280 100644
--- a/src/message.c
+++ b/src/message.c
@@ -1820,8 +1820,8 @@ str2special(
*sp = str + 1;
}
else
- // single-byte character or illegal byte
- *sp = str + 1;
+ // single-byte character, NUL or illegal byte
+ *sp = str + (*str == NUL ? 0 : 1);
// Make special keys and C0 control characters in <> form, also <M-Space>.
// Use <Space> only for lhs of a mapping.
diff --git a/src/testdir/test_menu.vim b/src/testdir/test_menu.vim
index c867162..df717cc 100644
--- a/src/testdir/test_menu.vim
+++ b/src/testdir/test_menu.vim
@@ -528,4 +528,17 @@ func Test_tmenu()
tunmenu Test
endfunc
+func Test_only_modifier()
+ exe "tmenu a.b \x80\xfc0"
+ let exp =<< trim [TEXT]
+ --- Menus ---
+ 500 a
+ 500 b
+ t - <T-2-^@>
+ [TEXT]
+ call assert_equal(exp, split(execute('tmenu'), "\n"))
+
+ tunmenu a.b
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
--
1.8.3.1

View File

@ -1,51 +0,0 @@
From d25f003342aca9889067f2e839963dfeccf1fe05 Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Thu, 30 Jun 2022 12:30:19 +0100
Subject: [PATCH] patch 9.0.0011: reading beyond the end of the line with put
command
Problem: Reading beyond the end of the line with put command.
Solution: Adjust the end mark position.
---
src/register.c | 2 ++
src/testdir/test_put.vim | 12 ++++++++++++
2 files changed, 14 insertions(+)
diff --git a/src/register.c b/src/register.c
index 93860ba..30e2001 100644
--- a/src/register.c
+++ b/src/register.c
@@ -1918,6 +1918,8 @@ do_put(
vim_memset(ptr, ' ', (size_t)spaces);
ptr += spaces;
}
+ else
+ totlen -= spaces; // didn't use these spaces
}
// may insert some spaces after the new text
diff --git a/src/testdir/test_put.vim b/src/testdir/test_put.vim
index aa5aa2b..66438bd 100644
--- a/src/testdir/test_put.vim
+++ b/src/testdir/test_put.vim
@@ -219,5 +219,17 @@ func Test_put_empty_register()
bwipe!
endfunc
+" this was putting the end mark after the end of the line
+func Test_put_visual_mode()
+ edit! SomeNewBuffer
+ set selection=exclusive
+ exe "norm o\t"
+ m0
+ sil! norm  p p
+
+ bwipe!
+ set selection&
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
--
1.8.3.1

View File

@ -1,51 +0,0 @@
From 3d51ce18ab1be4f9f6061568a4e7fabf00b21794 Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Fri, 1 Jul 2022 15:26:15 +0100
Subject: [PATCH] patch 9.0.0017: accessing memory beyond the end of the
line
Problem: Accessing memory beyond the end of the line.
Solution: Stop Visual mode when closing a window.
---
src/testdir/test_visual.vim | 12 ++++++++++++
src/window.c | 2 ++
2 files changed, 14 insertions(+)
diff --git a/src/testdir/test_visual.vim b/src/testdir/test_visual.vim
index c323062..e965266 100644
--- a/src/testdir/test_visual.vim
+++ b/src/testdir/test_visual.vim
@@ -1469,5 +1469,17 @@ func Test_visual_paste_clipboard()
bwipe!
endfunc
+func Test_visual_area_adjusted_when_hiding()
+ " The Visual area ended after the end of the line after :hide
+ call setline(1, 'xxx')
+ vsplit Xfile
+ call setline(1, 'xxxxxxxx')
+ norm! $o
+ hid
+ norm! zW
+ bwipe!
+ bwipe!
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/window.c b/src/window.c
index 992593b..c91ebbc 100644
--- a/src/window.c
+++ b/src/window.c
@@ -2594,6 +2594,8 @@ win_close(win_T *win, int free_buf)
*/
if (wp->w_buffer != curbuf)
{
+ reset_VIsual_and_resel(); // stop Visual mode
+
other_buffer = TRUE;
win->w_closing = TRUE;
apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, FALSE, curbuf);
--
1.8.3.1

View File

@ -1,46 +0,0 @@
From 27efc62f5d86afcb2ecb7565587fe8dea4b036fe Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Fri, 1 Jul 2022 16:35:45 +0100
Subject: [PATCH] patch 9.0.0018: going over the end of the typahead
Problem: Going over the end of the typahead.
Solution: Put a NUL after the typeahead.
---
src/term.c | 1 +
src/testdir/test_mapping.vim | 10 ++++++++++
2 files changed, 11 insertions(+)
diff --git a/src/term.c b/src/term.c
index 754ef82..7d7b84b 100644
--- a/src/term.c
+++ b/src/term.c
@@ -5393,6 +5393,7 @@ check_termcode(
if (*tp == ESC && !p_ek && (State & MODE_INSERT))
continue;
+ tp[len] = NUL;
key_name[0] = NUL; // no key name found yet
key_name[1] = NUL; // no key name found yet
modifiers = 0; // no modifiers yet
diff --git a/src/testdir/test_mapping.vim b/src/testdir/test_mapping.vim
index ace6453..2927ba7 100644
--- a/src/testdir/test_mapping.vim
+++ b/src/testdir/test_mapping.vim
@@ -1715,4 +1715,14 @@ func Test_map_after_timed_out_nop()
call delete('Xtest_map_after_timed_out_nop')
endfunc
+func Test_using_past_typeahead()
+ nnoremap :00 0
+ exe "norm :set \x80\xfb0=0\<CR>"
+ exe "sil norm :0\x0f\<C-U>\<CR>"
+
+ exe "norm :set \x80\xfb0=\<CR>"
+ nunmap :00
+endfunc
+
+
" vim: shiftwidth=2 sts=2 expandtab
--
1.8.3.1

View File

@ -1,61 +0,0 @@
From f12129f1714f7d2301935bb21d896609bdac221c Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Fri, 1 Jul 2022 19:58:30 +0100
Subject: [PATCH] patch 9.0.0020: with some completion reading past end of
string
Problem: With some completion reading past end of string.
Solution: Check the length of the string.
---
src/insexpand.c | 14 ++++++++++++--
src/testdir/test_ins_complete.vim | 8 ++++++++
2 files changed, 20 insertions(+), 2 deletions(-)
diff --git a/src/insexpand.c b/src/insexpand.c
index 4a5feac..734550f 100644
--- a/src/insexpand.c
+++ b/src/insexpand.c
@@ -2209,11 +2209,21 @@ ins_compl_stop(int c, int prev_mode, int retval)
// but only do this, if the Popup is still visible
if (c == Ctrl_E)
{
+ char_u *p = NULL;
+
ins_compl_delete();
if (compl_leader != NULL)
- ins_bytes(compl_leader + get_compl_len());
+ p = compl_leader;
else if (compl_first_match != NULL)
- ins_bytes(compl_orig_text + get_compl_len());
+ p = compl_orig_text;
+ if (p != NULL)
+ {
+ int compl_len = get_compl_len();
+ int len = (int)STRLEN(p);
+
+ if (len > compl_len)
+ ins_bytes_len(p + compl_len, len - compl_len);
+ }
retval = TRUE;
}
diff --git a/src/testdir/test_ins_complete.vim b/src/testdir/test_ins_complete.vim
index 365c646..20c2b4f 100644
--- a/src/testdir/test_ins_complete.vim
+++ b/src/testdir/test_ins_complete.vim
@@ -2184,4 +2184,12 @@ func Test_complete_smartindent()
delfunction! FooBarComplete
endfunc
+func Test_complete_overrun()
+ " this was going past the end of the copied text
+ new
+ sil norm si”0s0 
+ bwipe!
+endfunc
+
+
" vim: shiftwidth=2 sts=2 expandtab
--
1.8.3.1

View File

@ -1,90 +0,0 @@
From 5e59ea54c0c37c2f84770f068d95280069828774 Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Fri, 1 Jul 2022 22:26:20 +0100
Subject: [PATCH] patch 9.0.0021: invalid memory access when adding word to
spell word list
Problem: Invalid memory access when adding word with a control character to
the internal spell word list.
Solution: Disallow adding a word with control characters or a trailing
slash.
---
src/spellfile.c | 21 +++++++++++++++++++--
src/testdir/test_spell.vim | 15 +++++++++++++++
2 files changed, 34 insertions(+), 2 deletions(-)
diff --git a/src/spellfile.c b/src/spellfile.c
index f0d6d96..4a0de52 100644
--- a/src/spellfile.c
+++ b/src/spellfile.c
@@ -4367,6 +4367,23 @@ wordtree_alloc(spellinfo_T *spin)
}
/*
+ * Return TRUE if "word" contains valid word characters.
+ * Control characters and trailing '/' are invalid. Space is OK.
+ */
+ static int
+valid_spell_word(char_u *word)
+{
+ char_u *p;
+
+ if (enc_utf8 && !utf_valid_string(word, NULL))
+ return FALSE;
+ for (p = word; *p != NUL; p += mb_ptr2len(p))
+ if (*p < ' ' || (p[0] == '/' && p[1] == NUL))
+ return FALSE;
+ return TRUE;
+}
+
+/*
* Store a word in the tree(s).
* Always store it in the case-folded tree. For a keep-case word this is
* useful when the word can also be used with all caps (no WF_FIXCAP flag) and
@@ -4391,7 +4408,7 @@ store_word(
char_u *p;
// Avoid adding illegal bytes to the word tree.
- if (enc_utf8 && !utf_valid_string(word, NULL))
+ if (!valid_spell_word(word))
return FAIL;
(void)spell_casefold(curwin, word, len, foldword, MAXWLEN);
@@ -6194,7 +6211,7 @@ spell_add_word(
int i;
char_u *spf;
- if (enc_utf8 && !utf_valid_string(word, NULL))
+ if (!valid_spell_word(word))
{
emsg(_(e_illegal_character_in_word));
return;
diff --git a/src/testdir/test_spell.vim b/src/testdir/test_spell.vim
index 0fd5ed9..0187a17 100644
--- a/src/testdir/test_spell.vim
+++ b/src/testdir/test_spell.vim
@@ -854,6 +854,21 @@ func Test_spellsuggest_too_deep()
bwipe!
endfunc
+func Test_spell_good_word_invalid()
+ " This was adding a word with a 0x02 byte, which causes havoc.
+ enew
+ norm o0
+ sil! norm rzzWs00/
+ 2
+ sil! norm VzGprzzW
+ sil! norm z=
+
+ bwipe!
+ " clear the internal word list
+ set enc=latin1
+ set enc=utf-8
+endfunc
+
func LoadAffAndDic(aff_contents, dic_contents)
set enc=latin1
set spellfile=
--
1.8.3.1

View File

@ -1,54 +0,0 @@
From c6fdb15d423df22e1776844811d082322475e48a Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Sat, 2 Jul 2022 13:43:21 +0100
Subject: [PATCH] patch 9.0.0025: accessing beyond allocated memory with the
cmdline window
Problem: Accessing beyond allocated memory when using the cmdline window in
Ex mode.
Solution: Use "*" instead of "'<,'>" for Visual mode.
---
src/ex_docmd.c | 6 ++++--
src/testdir/test_cmdline.vim | 8 ++++++++
2 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/src/ex_docmd.c b/src/ex_docmd.c
index 271e7e2..697337c 100644
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -3118,9 +3118,11 @@ parse_command_modifiers(
size_t len = STRLEN(cmd_start);
// Special case: empty command uses "+":
- // "'<,'>mods" -> "mods'<,'>+
+ // "'<,'>mods" -> "mods *+
+ // Use "*" instead of "'<,'>" to avoid the command getting
+ // longer, in case is was allocated.
mch_memmove(orig_cmd, cmd_start, len);
- STRCPY(orig_cmd + len, "'<,'>+");
+ STRCPY(orig_cmd + len, " *+");
}
else
{
diff --git a/src/testdir/test_cmdline.vim b/src/testdir/test_cmdline.vim
index 3685336..f0498a1 100644
--- a/src/testdir/test_cmdline.vim
+++ b/src/testdir/test_cmdline.vim
@@ -2103,6 +2103,14 @@ func Test_cmdwin_insert_mode_close()
call assert_equal(1, winnr('$'))
endfunc
+func Test_cmdwin_ex_mode_with_modifier()
+ " this was accessing memory after allocated text in Ex mode
+ new
+ call setline(1, ['some', 'text', 'lines'])
+ silent! call feedkeys("gQnormal vq:atopleft\<C-V>\<CR>\<CR>", 'xt')
+ bwipe!
+endfunc
+
" test that ";" works to find a match at the start of the first line
func Test_zero_line_search()
new
--
1.8.3.1

View File

@ -1,65 +0,0 @@
From c5274dd12224421f2430b30c53b881b9403d649e Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Sat, 2 Jul 2022 15:10:00 +0100
Subject: [PATCH] patch 9.0.0026: accessing freed memory with diff put
Problem: Accessing freed memory with diff put.
Solution: Bail out when diff pointer is no longer valid.
---
src/diff.c | 24 ++++++++++++++++++++++--
1 files changed, 22 insertions(+), 2 deletions(-)
diff --git a/src/diff.c b/src/diff.c
index 91e5ae2..e4bafe2 100644
--- a/src/diff.c
+++ b/src/diff.c
@@ -2643,6 +2643,20 @@ nv_diffgetput(int put, long count)
}
/*
+ * Return TRUE if "diff" appears in the list of diff blocks of the current tab.
+ */
+ static int
+valid_diff(diff_T *diff)
+{
+ diff_T *dp;
+
+ for (dp = curtab->tp_first_diff; dp != NULL; dp = dp->df_next)
+ if (dp == diff)
+ return TRUE;
+ return FALSE;
+}
+
+/*
* ":diffget"
* ":diffput"
*/
@@ -2899,9 +2913,9 @@ ex_diffgetput(exarg_T *eap)
}
}
- // Adjust marks. This will change the following entries!
if (added != 0)
{
+ // Adjust marks. This will change the following entries!
mark_adjust(lnum, lnum + count - 1, (long)MAXLNUM, (long)added);
if (curwin->w_cursor.lnum >= lnum)
{
@@ -2923,7 +2937,13 @@ ex_diffgetput(exarg_T *eap)
#endif
vim_free(dfree);
}
- else
+
+ // mark_adjust() may have made "dp" invalid. We don't know where
+ // to continue then, bail out.
+ if (added != 0 && !valid_diff(dp))
+ break;
+
+ if (dfree == NULL)
// mark_adjust() may have changed the count in a wrong way
dp->df_count[idx_to] = new_count;
--
1.8.3.1

View File

@ -1,55 +0,0 @@
From 54e5fed6d27b747ff152cdb6edfb72ff60e70939 Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Mon, 4 Jul 2022 13:37:07 +0100
Subject: [PATCH] patch 9.0.0035: spell dump may go beyond end of an array
Problem: Spell dump may go beyond end of an array.
Solution: Limit the word length.
---
src/spell.c | 5 +++--
src/testdir/test_spell.vim | 12 ++++++++++++
2 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/src/spell.c b/src/spell.c
index d866a2d..24abce4 100644
--- a/src/spell.c
+++ b/src/spell.c
@@ -3996,9 +3996,10 @@ spell_dump_compl(
n = arridx[depth] + curi[depth];
++curi[depth];
c = byts[n];
- if (c == 0)
+ if (c == 0 || depth >= MAXWLEN - 1)
{
- // End of word, deal with the word.
+ // End of word or reached maximum length, deal with the
+ // word.
// Don't use keep-case words in the fold-case tree,
// they will appear in the keep-case tree.
// Only use the word when the region matches.
diff --git a/src/testdir/test_spell.vim b/src/testdir/test_spell.vim
index d3f56d8..a291eb5 100644
--- a/src/testdir/test_spell.vim
+++ b/src/testdir/test_spell.vim
@@ -285,6 +285,18 @@ func Test_spellreall()
bwipe!
endfunc
+func Test_spell_dump_word_length()
+ " this was running over MAXWLEN
+ new
+ noremap 0 0a0zW0000000
+ sil! norm 0z=0
+ sil norm 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+ sil! norm 0z=0
+
+ bwipe!
+ nunmap 0
+endfunc
+
" Test spellsuggest({word} [, {max} [, {capital}]])
func Test_spellsuggest()
" Verify suggestions are given even when spell checking is not enabled.
--
1.8.3.1

View File

@ -1,235 +0,0 @@
FROM CAEA66442D86E7BBBA3BF3DC202C3C0D549B9853 MON SEP 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Thu, 7 Jul 2022 19:42:04 +0100
Subject: [PATCH] patch 9.0.0045: reading past end of completion with a
long line
Problem: Reading past end of completion with a long line and 'infercase'
set.
Solution: Allocate the string if needed.
---
src/insexpand.c | 94 ++++++++++++++++++++++---------
src/testdir/test_ins_complete.vim | 16 ++++++
2 files changed, 82 insertions(+), 28 deletions(-)
diff --git a/src/insexpand.c b/src/insexpand.c
index 734550f..0ecb656 100644
--- a/src/insexpand.c
+++ b/src/insexpand.c
@@ -524,29 +524,32 @@ ins_compl_accept_char(int c)
/*
* Get the completed text by inferring the case of the originally typed text.
+ * If the result is in allocated memory "tofree" is set to it.
*/
static char_u *
ins_compl_infercase_gettext(
char_u *str,
- int actual_len,
- int actual_compl_length,
- int min_len)
+ int char_len,
+ int compl_char_len,
+ int min_len,
+ char_u **tofree)
{
int *wca; // Wide character array.
char_u *p;
int i, c;
int has_lower = FALSE;
int was_letter = FALSE;
+ garray_T gap;
IObuff[0] = NUL;
// Allocate wide character array for the completion and fill it.
- wca = ALLOC_MULT(int, actual_len);
+ wca = ALLOC_MULT(int, char_len);
if (wca == NULL)
return IObuff;
p = str;
- for (i = 0; i < actual_len; ++i)
+ for (i = 0; i < char_len; ++i)
if (has_mbyte)
wca[i] = mb_ptr2char_adv(&p);
else
@@ -566,7 +569,7 @@ ins_compl_infercase_gettext(
if (MB_ISUPPER(wca[i]))
{
// Rule 1 is satisfied.
- for (i = actual_compl_length; i < actual_len; ++i)
+ for (i = compl_char_len; i < char_len; ++i)
wca[i] = MB_TOLOWER(wca[i]);
break;
}
@@ -587,7 +590,7 @@ ins_compl_infercase_gettext(
if (was_letter && MB_ISUPPER(c) && MB_ISLOWER(wca[i]))
{
// Rule 2 is satisfied.
- for (i = actual_compl_length; i < actual_len; ++i)
+ for (i = compl_char_len; i < char_len; ++i)
wca[i] = MB_TOUPPER(wca[i]);
break;
}
@@ -610,20 +613,52 @@ ins_compl_infercase_gettext(
}
// Generate encoding specific output from wide character array.
- // Multi-byte characters can occupy up to five bytes more than
- // ASCII characters, and we also need one byte for NUL, so stay
- // six bytes away from the edge of IObuff.
p = IObuff;
i = 0;
- while (i < actual_len && (p - IObuff + 6) < IOSIZE)
- if (has_mbyte)
+ ga_init2(&gap, 1, 500);
+ while (i < char_len)
+ {
+ if (gap.ga_data != NULL)
+ {
+ if (ga_grow(&gap, 10) == FAIL)
+ {
+ ga_clear(&gap);
+ return (char_u *)"[failed]";
+ }
+ p = (char_u *)gap.ga_data + gap.ga_len;
+ if (has_mbyte)
+ gap.ga_len += (*mb_char2bytes)(wca[i++], p);
+ else
+ {
+ *p = wca[i++];
+ ++gap.ga_len;
+ }
+ }
+ else if ((p - IObuff) + 6 >= IOSIZE)
+ {
+ // Multi-byte characters can occupy up to five bytes more than
+ // ASCII characters, and we also need one byte for NUL, so when
+ // getting to six bytes from the edge of IObuff switch to using a
+ // growarray. Add the character in the next round.
+ if (ga_grow(&gap, IOSIZE) == FAIL)
+ return (char_u *)"[failed]";
+ STRCPY(gap.ga_data, IObuff);
+ gap.ga_len = STRLEN(IObuff);
+ }
+ else if (has_mbyte)
p += (*mb_char2bytes)(wca[i++], p);
else
*(p++) = wca[i++];
- *p = NUL;
-
+ }
vim_free(wca);
+ if (gap.ga_data != NULL)
+ {
+ *tofree = gap.ga_data;
+ return gap.ga_data;
+ }
+
+ *p = NUL;
return IObuff;
}
@@ -644,10 +679,12 @@ ins_compl_add_infercase(
{
char_u *str = str_arg;
char_u *p;
- int actual_len; // Take multi-byte characters
- int actual_compl_length; // into account.
+ int char_len; // count multi-byte characters
+ int compl_char_len;
int min_len;
int flags = 0;
+ int res;
+ char_u *tofree = NULL;
if (p_ic && curbuf->b_p_inf && len > 0)
{
@@ -657,44 +694,45 @@ ins_compl_add_infercase(
if (has_mbyte)
{
p = str;
- actual_len = 0;
+ char_len = 0;
while (*p != NUL)
{
MB_PTR_ADV(p);
- ++actual_len;
+ ++char_len;
}
}
else
- actual_len = len;
+ char_len = len;
// Find actual length of original text.
if (has_mbyte)
{
p = compl_orig_text;
- actual_compl_length = 0;
+ compl_char_len = 0;
while (*p != NUL)
{
MB_PTR_ADV(p);
- ++actual_compl_length;
+ ++compl_char_len;
}
}
else
- actual_compl_length = compl_length;
+ compl_char_len = compl_length;
- // "actual_len" may be smaller than "actual_compl_length" when using
+ // "char_len" may be smaller than "compl_char_len" when using
// thesaurus, only use the minimum when comparing.
- min_len = actual_len < actual_compl_length
- ? actual_len : actual_compl_length;
+ min_len = char_len < compl_char_len ? char_len : compl_char_len;
- str = ins_compl_infercase_gettext(str, actual_len, actual_compl_length,
- min_len);
+ str = ins_compl_infercase_gettext(str, char_len,
+ compl_char_len, min_len, &tofree);
}
if (cont_s_ipos)
flags |= CP_CONT_S_IPOS;
if (icase)
flags |= CP_ICASE;
- return ins_compl_add(str, len, fname, NULL, NULL, dir, flags, FALSE);
+ res = ins_compl_add(str, len, fname, NULL, NULL, dir, flags, FALSE);
+ vim_free(tofree);
+ return res;
}
/*
diff --git a/src/testdir/test_ins_complete.vim b/src/testdir/test_ins_complete.vim
index 20c2b4f..f2daa02 100644
--- a/src/testdir/test_ins_complete.vim
+++ b/src/testdir/test_ins_complete.vim
@@ -2192,4 +2192,20 @@ func Test_complete_overrun()
endfunc
+func Test_infercase_very_long_line()
+ " this was truncating the line when inferring case
+ new
+ let longLine = "blah "->repeat(300)
+ let verylongLine = "blah "->repeat(400)
+ call setline(1, verylongLine)
+ call setline(2, longLine)
+ set ic infercase
+ exe "normal 2Go\<C-X>\<C-L>\<Esc>"
+ call assert_equal(longLine, getline(3))
+
+ bwipe!
+ set noic noinfercase
+endfunc
+
+
" vim: shiftwidth=2 sts=2 expandtab
--
2.36.1

View File

@ -1,50 +0,0 @@
From baefde14550231f6468ac2ed2ed495bc381c0c92 Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Thu, 7 Jul 2022 19:59:49 +0100
Subject: [PATCH] patch 9.0.0046: reading past end of completion with
duplicate match
Problem: Reading past end of completion with duplicate match.
Solution: Check string length
---
src/insexpand.c | 3 ++-
src/testdir/test_ins_complete.vim | 10 ++++++++++
2 files changed, 12 insertions(+), 1 deletion(-)
diff --git a/src/insexpand.c b/src/insexpand.c
index 0ecb656..9c598a8 100644
--- a/src/insexpand.c
+++ b/src/insexpand.c
@@ -786,7 +786,8 @@ ins_compl_add(
{
if (!match_at_original_text(match)
&& STRNCMP(match->cp_str, str, len) == 0
- && match->cp_str[len] == NUL)
+ && ((int)STRLEN(match->cp_str) <= len
+ || match->cp_str[len] == NUL))
return NOTDONE;
match = match->cp_next;
} while (match != NULL && !is_first_match(match));
diff --git a/src/testdir/test_ins_complete.vim b/src/testdir/test_ins_complete.vim
index 5e5b1bb..2be6d06 100644
--- a/src/testdir/test_ins_complete.vim
+++ b/src/testdir/test_ins_complete.vim
@@ -2112,5 +2112,15 @@ func Test_infercase_very_long_line()
set noic noinfercase
endfunc
+func Test_ins_complete_add()
+ " this was reading past the end of allocated memory
+ new
+ norm o
+ norm 7o€€
+ sil! norm o
+
+ bwipe!
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
--
1.8.3.1

View File

@ -1,79 +0,0 @@
From 32acf1f1a72ebb9d8942b9c9d80023bf1bb668ea Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Thu, 7 Jul 2022 22:20:31 +0100
Subject: [PATCH] patch 9.0.0047: using freed memory with recursive
substitute
Problem: Using freed memory with recursive substitute.
Solution: Always make a copy for reg_prev_sub.
---
src/ex_cmds.c | 11 ++++++++++-
src/regexp.c | 8 ++++----
src/testdir/test_regexp_latin.vim | 11 +++++++++++
3 files changed, 25 insertions(+), 5 deletions(-)
diff --git a/src/ex_cmds.c b/src/ex_cmds.c
index eb3016f..5253863 100644
--- a/src/ex_cmds.c
+++ b/src/ex_cmds.c
@@ -3994,7 +3994,16 @@ ex_substitute(exarg_T *eap)
sub_copy = sub;
}
else
- sub = regtilde(sub, magic_isset());
+ {
+ char_u *newsub = regtilde(sub, magic_isset());
+
+ if (newsub != sub)
+ {
+ // newsub was allocated, free it later.
+ sub_copy = newsub;
+ sub = newsub;
+ }
+ }
/*
* Check for a match on each line.
diff --git a/src/regexp.c b/src/regexp.c
index 2cbe64e..f35a5e8 100644
--- a/src/regexp.c
+++ b/src/regexp.c
@@ -1766,11 +1766,11 @@ regtilde(char_u *source, int magic)
}
}
+ // Store a copy of newsub in reg_prev_sub. It is always allocated,
+ // because recursive calls may make the returned string invalid.
vim_free(reg_prev_sub);
- if (newsub != source) // newsub was allocated, just keep it
- reg_prev_sub = newsub;
- else // no ~ found, need to save newsub
- reg_prev_sub = vim_strsave(newsub);
+ reg_prev_sub = vim_strsave(newsub);
+
return newsub;
}
diff --git a/src/testdir/test_regexp_latin.vim b/src/testdir/test_regexp_latin.vim
index 1fe4699..dce6709 100644
--- a/src/testdir/test_regexp_latin.vim
+++ b/src/testdir/test_regexp_latin.vim
@@ -1114,4 +1114,15 @@ func Test_using_two_engines_pattern()
bwipe!
endfunc
+func Test_recursive_substitute_expr()
+ new
+ func Repl()
+ s
+ endfunc
+ silent! s/\%')/~\=Repl()
+
+ bwipe!
+ delfunc Repl
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
--
1.8.3.1

View File

@ -1,46 +0,0 @@
From b9e717367c395490149495cf375911b5d9de889e Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Sat, 23 Jul 2022 06:53:08 +0100
Subject: [PATCH] patch 9.0.0060: accessing uninitialized memory when
completing long line
Problem: Accessing uninitialized memory when completing long line.
Solution: Terminate string with NUL.
---
src/insexpand.c | 1 +
src/testdir/test_ins_complete.vim | 7 +++++++
2 files changed, 8 insertions(+)
diff --git a/src/insexpand.c b/src/insexpand.c
index b49a631..c505158 100644
--- a/src/insexpand.c
+++ b/src/insexpand.c
@@ -642,6 +642,7 @@ ins_compl_infercase_gettext(
// growarray. Add the character in the next round.
if (ga_grow(&gap, IOSIZE) == FAIL)
return (char_u *)"[failed]";
+ *p = NUL;
STRCPY(gap.ga_data, IObuff);
gap.ga_len = (int)STRLEN(IObuff);
}
diff --git a/src/testdir/test_ins_complete.vim b/src/testdir/test_ins_complete.vim
index 2be6d06..7bebc5d 100644
--- a/src/testdir/test_ins_complete.vim
+++ b/src/testdir/test_ins_complete.vim
@@ -2108,6 +2108,13 @@ func Test_infercase_very_long_line()
exe "normal 2Go\<C-X>\<C-L>\<Esc>"
call assert_equal(longLine, getline(3))
+ " check that the too long text is NUL terminated
+ %del
+ norm o
+ norm 1987ax
+ exec "norm ox\<C-X>\<C-L>"
+ call assert_equal(repeat('x', 1987), getline(3))
+
bwipe!
set noic noinfercase
endfunc
--
1.8.3.1

View File

@ -1,47 +0,0 @@
From a6f9e300161f4cb54713da22f65b261595e8e614 Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Thu, 28 Jul 2022 21:51:37 +0100
Subject: [PATCH] patch 9.0.0102: reading past end of line with insert mode
completion
Problem: Reading past end of line with insert mode completion.
Solution: Check text length.
---
src/insexpand.c | 2 +-
src/testdir/test_ins_complete.vim | 8 ++++++++
2 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/src/insexpand.c b/src/insexpand.c
index 7339ce9..fc3eff0 100644
--- a/src/insexpand.c
+++ b/src/insexpand.c
@@ -3501,7 +3501,7 @@ ins_comp_get_next_word_or_line(
{
char_u *tmp_ptr = ptr;
- if (compl_status_adding())
+ if (compl_status_adding() && compl_length <= (int)STRLEN(tmp_ptr))
{
tmp_ptr += compl_length;
// Skip if already inside a word.
diff --git a/src/testdir/test_ins_complete.vim b/src/testdir/test_ins_complete.vim
index 35c5785..2b0a294 100644
--- a/src/testdir/test_ins_complete.vim
+++ b/src/testdir/test_ins_complete.vim
@@ -2142,5 +2142,13 @@ func Test_ins_complete_add()
bwipe!
endfunc
+func Test_ins_complete_end_of_line()
+ " this was reading past the end of the line
+ new
+ norm 8o€ý 
+ sil! norm o
+
+ bwipe!
+endfunc
" vim: shiftwidth=2 sts=2 expandtab
--
1.8.3.1

Binary file not shown.

View File

@ -1,65 +0,0 @@
From f50940531dd57135fe60aa393ac9d3281f352d88 Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Fri, 29 Jul 2022 16:22:25 +0100
Subject: [PATCH 002/123] patch 9.0.0105: illegal memory access when pattern
starts with illegal byte
Problem: Illegal memory access when pattern starts with illegal byte.
Solution: Do not match a character with an illegal byte.
---
src/regexp.c | 6 +++++-
src/testdir/test_regexp_utf8.vim | 15 +++++++++++++++
2 files changed, 20 insertions(+), 1 deletion(-)
diff --git a/src/regexp.c b/src/regexp.c
index 1a5cfd0..bec0464 100644
--- a/src/regexp.c
+++ b/src/regexp.c
@@ -1641,7 +1641,11 @@ cstrchr(char_u *s, int c)
{
if (enc_utf8 && c > 0x80)
{
- if (utf_fold(utf_ptr2char(p)) == cc)
+ int uc = utf_ptr2char(p);
+
+ // Do not match an illegal byte. E.g. 0xff matches 0xc3 0xbf,
+ // not 0xff.
+ if ((uc < 0x80 || uc != *p) && utf_fold(uc) == cc)
return p;
}
else if (*p == c || *p == cc)
diff --git a/src/testdir/test_regexp_utf8.vim b/src/testdir/test_regexp_utf8.vim
index d88e263..e7672dd 100644
--- a/src/testdir/test_regexp_utf8.vim
+++ b/src/testdir/test_regexp_utf8.vim
@@ -1,5 +1,7 @@
" Tests for regexp in utf8 encoding
+source shared.vim
+
func s:equivalence_test()
let str = "AÀÁÂÃÄÅĀĂĄǍǞǠǺȂȦȺḀẠẢẤẦẨẪẬẮẰẲẴẶ BƁɃḂḄḆ CÇĆĈĊČƇȻḈꞒ DĎĐƊḊḌḎḐḒ EÈÉÊËĒĔĖĘĚȄȆȨɆḔḖḘḚḜẸẺẼẾỀỂỄỆ FƑḞ GĜĞĠĢƓǤǦǴḠꞠ HĤĦȞḢḤḦḨḪⱧ IÌÍÎÏĨĪĬĮİƗǏȈȊḬḮỈỊ JĴɈ KĶƘǨḰḲḴⱩꝀ LĹĻĽĿŁȽḶḸḺḼⱠ MḾṀṂ NÑŃŅŇǸṄṆṈṊꞤ OÒÓÔÕÖØŌŎŐƟƠǑǪǬǾȌȎȪȬȮȰṌṎṐṒỌỎỐỒỔỖỘỚỜỞỠỢ PƤṔṖⱣ QɊ RŔŖŘȐȒɌṘṚṜṞⱤꞦ SŚŜŞŠȘṠṢṤṦṨⱾꞨ TŢŤŦƬƮȚȾṪṬṮṰ UÙÚÛÜŨŪŬŮŰƯǕǙǛǓǗȔȖɄṲṴṶṸṺỤỦỨỪỬỮỰ VƲṼṾ WŴẀẂẄẆẈ XẊẌ YÝŶŸƳȲɎẎỲỴỶỸ ZŹŻŽƵẐẒẔⱫ aàáâãäåāăąǎǟǡǻȃȧᶏḁẚạảấầẩẫậắằẳẵặⱥ bƀɓᵬᶀḃḅḇ cçćĉċčƈȼḉꞓꞔ dďđɗᵭᶁᶑḋḍḏḑḓ eèéêëēĕėęěȅȇȩɇᶒḕḗḙḛḝẹẻẽếềểễệ fƒᵮᶂḟ gĝğġģǥǧǵɠḡꞡ hĥħȟḣḥḧḩḫẖⱨꞕ iìíîïĩīĭįǐȉȋɨᶖḭḯỉị jĵǰɉ kķƙǩᶄḱḳḵⱪꝁ lĺļľŀłƚḷḹḻḽⱡ mᵯḿṁṃ nñńņňʼnǹᵰᶇṅṇṉṋꞥ oòóôõöøōŏőơǒǫǭǿȍȏȫȭȯȱɵṍṏṑṓọỏốồổỗộớờởỡợ pƥᵱᵽᶈṕṗ qɋʠ rŕŗřȑȓɍɽᵲᵳᶉṛṝṟꞧ sśŝşšșȿᵴᶊṡṣṥṧṩꞩ tţťŧƫƭțʈᵵṫṭṯṱẗⱦ uùúûüũūŭůűųǚǖưǔǘǜȕȗʉᵾᶙṳṵṷṹṻụủứừửữự vʋṽṿ wŵẁẃẅẇẉẘ xẋẍ yýÿŷƴȳɏẏẙỳỵỷỹ zźżžƶᵶᶎẑẓẕⱬ"
let groups = split(str)
@@ -560,6 +562,19 @@ func Test_match_invalid_byte()
call delete('Xinvalid')
endfunc
+func Test_match_illegal_byte()
+ let lines =<< trim END
+ silent! buffer ÿ\c
+ next ÿ
+ 0scriptnames
+ source
+ END
+ call writefile(lines, 'Xregexp')
+ call system(GetVimCommand() .. ' -X -Z -e -s -S Xregexp -c qa!')
+
+ call delete('Xregexp')
+endfunc
+
func Test_match_too_complicated()
set regexpengine=1
exe "noswapfile vsplit \xeb\xdb\x99"
--
1.8.3.1

View File

@ -1,67 +0,0 @@
From 4e677b9c40ccbc5f090971b31dc2fe07bf05541d Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Thu, 28 Jul 2022 18:44:27 +0100
Subject: [PATCH] patch 9.0.0101: invalid memory access in diff mode with "dp"
and undo
Problem: Invalid memory access in diff mode with "dp" and undo.
Solution: Make sure the line number does not go below one.
---
src/diff.c | 9 ++++++---
src/testdir/test_diffmode.vim | 14 ++++++++++++++
2 files changed, 20 insertions(+), 3 deletions(-)
diff --git a/src/diff.c b/src/diff.c
index e4bafe2..fb43eee 100644
--- a/src/diff.c
+++ b/src/diff.c
@@ -464,7 +464,10 @@ diff_mark_adjust_tp(
for (i = 0; i < DB_COUNT; ++i)
if (tp->tp_diffbuf[i] != NULL && i != idx)
{
- dp->df_lnum[i] -= off;
+ if (dp->df_lnum[i] > off)
+ dp->df_lnum[i] -= off;
+ else
+ dp->df_lnum[i] = 1;
dp->df_count[i] += n;
}
}
@@ -2863,8 +2866,8 @@ ex_diffgetput(exarg_T *eap)
{
// remember deleting the last line of the buffer
buf_empty = curbuf->b_ml.ml_line_count == 1;
- ml_delete(lnum);
- --added;
+ if (ml_delete(lnum) == OK)
+ --added;
}
for (i = 0; i < dp->df_count[idx_from] - start_skip - end_skip; ++i)
{
diff --git a/src/testdir/test_diffmode.vim b/src/testdir/test_diffmode.vim
index dcacd55..41f7fe3 100644
--- a/src/testdir/test_diffmode.vim
+++ b/src/testdir/test_diffmode.vim
@@ -1628,5 +1628,19 @@ func Test_diff_manipulations()
%bwipe!
endfunc
+" This was causing the line number in the diff block to go below one.
+" FIXME: somehow this causes a valgrind error when run directly but not when
+" run as a test.
+func Test_diff_put_and_undo()
+ set diff
+ next 0
+ split 00
+ sil! norm o0gguudpo0ggJuudp
+
+ bwipe!
+ bwipe!
+ set nodiff
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
--
1.8.3.1

View File

@ -1,58 +0,0 @@
From dbdd16b62560413abcc3c8e893cc3010ccf31666 Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Sun, 14 Aug 2022 21:46:07 +0100
Subject: [PATCH] patch 9.0.0212: invalid memory access when compiling :unlet
Problem: Invalid memory access when compiling :unlet.
Solution: Don't read past the end of the line.
---
src/testdir/test_vim9_cmd.vim | 11 +++++++++--
src/vim9cmds.c | 6 ++++++
2 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/src/testdir/test_vim9_cmd.vim b/src/testdir/test_vim9_cmd.vim
index 16f534e..a40f261 100644
--- a/src/testdir/test_vim9_cmd.vim
+++ b/src/testdir/test_vim9_cmd.vim
@@ -1704,12 +1704,19 @@ def Test_lockvar()
lines =<< trim END
def _()
- s:0([], s:0)
lockv
enddef
defcomp
END
- v9.CheckScriptFailure(lines, 'E179', 2)
+ v9.CheckScriptFailure(lines, 'E179', 1)
+
+ lines =<< trim END
+ def T()
+ unlet
+ enddef
+ defcomp
+ END
+ v9.CheckScriptFailure(lines, 'E179', 1)
enddef
def Test_substitute_expr()
diff --git a/src/vim9cmds.c b/src/vim9cmds.c
index 35a3821..93032d6 100644
--- a/src/vim9cmds.c
+++ b/src/vim9cmds.c
@@ -92,6 +92,12 @@ free_locals(cctx_T *cctx)
int
check_vim9_unlet(char_u *name)
{
+ if (*name == NUL)
+ {
+ semsg(_(e_argument_required_for_str), "unlet");
+ return FAIL;
+ }
+
if (name[1] != ':' || vim_strchr((char_u *)"gwtb", *name) == NULL)
{
// "unlet s:var" is allowed in legacy script.
--
2.36.1

View File

@ -1,75 +0,0 @@
From 249e1b903a9c0460d618f6dcc59aeb8c03b24b20 Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Sun, 14 Aug 2022 22:23:02 +0100
Subject: [PATCH] patch 9.0.0213: using freed memory with error in assert
argument
Problem: Using freed memory with error in assert argument.
Solution: Make a copy of the error.
---
src/testdir/test_assert.vim | 4 ++++
src/testing.c | 18 ++++++++++++------
2 files changed, 16 insertions(+), 6 deletions(-)
diff --git a/src/testdir/test_assert.vim b/src/testdir/test_assert.vim
index 27b2d73..7c9d090 100644
--- a/src/testdir/test_assert.vim
+++ b/src/testdir/test_assert.vim
@@ -291,6 +291,10 @@ func Test_assert_fail_fails()
let exp = v:exception
endtry
call assert_match("E1174: String required for argument 5", exp)
+
+ call assert_equal(1, assert_fails('c0', ['', '\1']))
+ call assert_match("Expected '\\\\\\\\1' but got 'E939: Positive count required: c0': c0", v:errors[0])
+ call remove(v:errors, 0)
endfunc
func Test_assert_fails_in_try_block()
diff --git a/src/testing.c b/src/testing.c
index c49df4b..43b8d20 100644
--- a/src/testing.c
+++ b/src/testing.c
@@ -597,6 +597,7 @@ f_assert_fails(typval_T *argvars, typval_T *rettv)
int save_trylevel = trylevel;
int called_emsg_before = called_emsg;
char *wrong_arg_msg = NULL;
+ char_u *tofree = NULL;
if (check_for_string_or_number_arg(argvars, 0) == FAIL
|| check_for_opt_string_or_list_arg(argvars, 1) == FAIL
@@ -660,13 +661,17 @@ f_assert_fails(typval_T *argvars, typval_T *rettv)
}
else if (list->lv_len == 2)
{
- tv = &list->lv_u.mat.lv_last->li_tv;
- actual = get_vim_var_str(VV_ERRMSG);
- expected = tv_get_string_buf_chk(tv, buf);
- if (!pattern_match(expected, actual, FALSE))
+ // make a copy, an error in pattern_match() may free it
+ tofree = actual = vim_strsave(get_vim_var_str(VV_ERRMSG));
+ if (actual != NULL)
{
- error_found = TRUE;
- expected_str = expected;
+ tv = &list->lv_u.mat.lv_last->li_tv;
+ expected = tv_get_string_buf_chk(tv, buf);
+ if (!pattern_match(expected, actual, FALSE))
+ {
+ error_found = TRUE;
+ expected_str = expected;
+ }
}
}
}
@@ -749,6 +754,7 @@ theend:
msg_scrolled = 0;
lines_left = Rows;
VIM_CLEAR(emsg_assert_fails_msg);
+ vim_free(tofree);
set_vim_var_string(VV_ERRMSG, NULL, 0);
if (wrong_arg_msg != NULL)
emsg(_(wrong_arg_msg));
--
2.36.1

View File

@ -1,66 +0,0 @@
From d1d8f6bacb489036d0fd479c9dd3c0102c988889 Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Sun, 14 Aug 2022 21:28:32 +0100
Subject: [PATCH] patch 9.0.0211: invalid memory access when compiling :lockvar
Problem: Invalid memory access when compiling :lockvar.
Solution: Don't read past the end of the line.
---
src/testdir/test_vim9_cmd.vim | 9 +++++++++
src/vim9cmds.c | 9 +++++++--
2 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/src/testdir/test_vim9_cmd.vim b/src/testdir/test_vim9_cmd.vim
index 7db8e50..16f534e 100644
--- a/src/testdir/test_vim9_cmd.vim
+++ b/src/testdir/test_vim9_cmd.vim
@@ -1701,6 +1701,15 @@ def Test_lockvar()
UnLockIt()
END
v9.CheckScriptFailure(lines, 'E46', 1)
+
+ lines =<< trim END
+ def _()
+ s:0([], s:0)
+ lockv
+ enddef
+ defcomp
+ END
+ v9.CheckScriptFailure(lines, 'E179', 2)
enddef
def Test_substitute_expr()
diff --git a/src/vim9cmds.c b/src/vim9cmds.c
index ad32c32..35a3821 100644
--- a/src/vim9cmds.c
+++ b/src/vim9cmds.c
@@ -188,10 +188,17 @@ compile_lock_unlock(
size_t len;
char_u *buf;
isntype_T isn = ISN_EXEC;
+ char *cmd = eap->cmdidx == CMD_lockvar ? "lockvar" : "unlockvar";
if (cctx->ctx_skip == SKIP_YES)
return OK;
+ if (*p == NUL)
+ {
+ semsg(_(e_argument_required_for_str), cmd);
+ return FAIL;
+ }
+
// Cannot use :lockvar and :unlockvar on local variables.
if (p[1] != ':')
{
@@ -223,8 +230,6 @@ compile_lock_unlock(
ret = FAIL;
else
{
- char *cmd = eap->cmdidx == CMD_lockvar ? "lockvar" : "unlockvar";
-
if (deep < 0)
vim_snprintf((char *)buf, len, "%s! %s", cmd, p);
else
--
2.36.1

View File

@ -1,61 +0,0 @@
From e98c88c44c308edaea5994b8ad4363e65030968c Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Tue, 16 Aug 2022 14:51:53 +0100
Subject: [PATCH] patch 9.0.0218: reading before the start of the line
Problem: Reading before the start of the line.
Solution: When displaying "$" check the column is not negative.
---
src/edit.c | 3 ++-
src/proto/edit.pro | 2 +-
src/testdir/test_cmdline.vim | 8 ++++++++
3 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/src/edit.c b/src/edit.c
index a8e695c..96f47bd 100644
--- a/src/edit.c
+++ b/src/edit.c
@@ -1741,8 +1741,9 @@ edit_unputchar(void)
* Only works when cursor is in the line that changes.
*/
void
-display_dollar(colnr_T col)
+display_dollar(colnr_T col_arg)
{
+ colnr_T col = col_arg < 0 ? 0 : col_arg;
colnr_T save_col;
if (!redrawing())
diff --git a/src/proto/edit.pro b/src/proto/edit.pro
index a233e40..f35ec1e 100644
--- a/src/proto/edit.pro
+++ b/src/proto/edit.pro
@@ -5,7 +5,7 @@ void ins_redraw(int ready);
void edit_putchar(int c, int highlight);
void set_insstart(linenr_T lnum, int col);
void edit_unputchar(void);
-void display_dollar(colnr_T col);
+void display_dollar(colnr_T col_arg);
void undisplay_dollar(void);
void truncate_spaces(char_u *line);
void backspace_until_column(int col);
diff --git a/src/testdir/test_cmdline.vim b/src/testdir/test_cmdline.vim
index f0498a1..08e2de7 100644
--- a/src/testdir/test_cmdline.vim
+++ b/src/testdir/test_cmdline.vim
@@ -3439,4 +3439,12 @@ func Test_long_error_message()
silent! norm Q00000000000000     000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000                                                                                                                                                                                                                        
endfunc
+func Test_cmdwin_virtual_edit()
+ enew!
+ set ve=all cpo+=$
+ silent normal q/s
+
+ set ve= cpo-=$
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
--
2.36.1

View File

@ -1,103 +0,0 @@
From f6d39c31d2177549a986d170e192d8351bd571e2 Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Tue, 16 Aug 2022 17:50:38 +0100
Subject: [PATCH] patch 9.0.0220: invalid memory access with for loop over NULL
string
Problem: Invalid memory access with for loop over NULL string.
Solution: Make sure mb_ptr2len() consistently returns zero for NUL.
---
src/globals.h | 3 ++-
src/mbyte.c | 21 +++++++++++++--------
src/testdir/test_eval_stuff.vim | 12 ++++++++++++
3 files changed, 27 insertions(+), 9 deletions(-)
diff --git a/src/globals.h b/src/globals.h
index 888f6e9..9b40be4 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -1033,7 +1033,8 @@ EXTERN vimconv_T output_conv; // type of output conversion
* (DBCS).
* The value is set in mb_init();
*/
-// length of char in bytes, including following composing chars
+// Length of char in bytes, including any following composing chars.
+// NUL has length zero.
EXTERN int (*mb_ptr2len)(char_u *p) INIT(= latin_ptr2len);
// idem, with limit on string length
diff --git a/src/mbyte.c b/src/mbyte.c
index 3656880..782a7ad 100644
--- a/src/mbyte.c
+++ b/src/mbyte.c
@@ -1077,24 +1077,28 @@ dbcs_char2bytes(int c, char_u *buf)
}
/*
- * mb_ptr2len() function pointer.
- * Get byte length of character at "*p" but stop at a NUL.
- * For UTF-8 this includes following composing characters.
- * Returns 0 when *p is NUL.
+ * Get byte length of character at "*p". Returns zero when "*p" is NUL.
+ * Used for mb_ptr2len() when 'encoding' latin.
*/
int
latin_ptr2len(char_u *p)
{
- return MB_BYTE2LEN(*p);
+ return *p == NUL ? 0 : 1;
}
+/*
+ * Get byte length of character at "*p". Returns zero when "*p" is NUL.
+ * Used for mb_ptr2len() when 'encoding' DBCS.
+ */
static int
-dbcs_ptr2len(
- char_u *p)
+dbcs_ptr2len(char_u *p)
{
int len;
- // Check if second byte is not missing.
+ if (*p == NUL)
+ return 0;
+
+ // if the second byte is missing the length is 1
len = MB_BYTE2LEN(*p);
if (len == 2 && p[1] == NUL)
len = 1;
@@ -2105,6 +2109,7 @@ utf_ptr2len_len(char_u *p, int size)
/*
* Return the number of bytes the UTF-8 encoding of the character at "p" takes.
* This includes following composing characters.
+ * Returns zero for NUL.
*/
int
utfc_ptr2len(char_u *p)
diff --git a/src/testdir/test_eval_stuff.vim b/src/testdir/test_eval_stuff.vim
index c63082e..313d791 100644
--- a/src/testdir/test_eval_stuff.vim
+++ b/src/testdir/test_eval_stuff.vim
@@ -75,6 +75,18 @@ func Test_for_invalid()
redraw
endfunc
+func Test_for_over_null_string()
+ let save_enc = &enc
+ set enc=iso8859
+ let cnt = 0
+ for c in test_null_string()
+ let cnt += 1
+ endfor
+ call assert_equal(0, cnt)
+
+ let &enc = save_enc
+endfunc
+
func Test_readfile_binary()
new
call setline(1, ['one', 'two', 'three'])
--
2.36.1

View File

@ -1,72 +0,0 @@
From 1889f499a4f248cd84e0e0bf6d0d820016774494 Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Tue, 16 Aug 2022 19:34:44 +0100
Subject: [PATCH] patch 9.0.0221: accessing freed memory if compiling nested
function fails
Problem: Accessing freed memory if compiling nested function fails.
Solution: Mess up the variable name so that it won't be found.
---
src/testdir/test_vim9_func.vim | 12 ++++++++++++
src/vim9compile.c | 7 +++++--
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim
index 33a6615..426fde4 100644
--- a/src/testdir/test_vim9_func.vim
+++ b/src/testdir/test_vim9_func.vim
@@ -907,6 +907,18 @@ def Test_nested_function()
v9.CheckScriptFailure(lines, 'E1173: Text found after enddef: burp', 3)
enddef
+def Test_nested_function_fails()
+ var lines =<< trim END
+ def T()
+ def Func(g: string):string
+ enddef
+ Func()
+ enddef
+ silent! defcompile
+ END
+ v9.CheckScriptFailure(lines, 'E1069:')
+enddef
+
def Test_not_nested_function()
echo printf('%d',
function('len')('xxx'))
diff --git a/src/vim9compile.c b/src/vim9compile.c
index b7f590e..fb39997 100644
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -822,6 +822,7 @@ compile_nested_function(exarg_T *eap, cctx_T *cctx, garray_T *lines_to_free)
int r = FAIL;
compiletype_T compile_type;
isn_T *funcref_isn = NULL;
+ lvar_T *lvar = NULL;
if (eap->forceit)
{
@@ -928,9 +929,8 @@ compile_nested_function(exarg_T *eap, cctx_T *cctx, garray_T *lines_to_free)
else
{
// Define a local variable for the function reference.
- lvar_T *lvar = reserve_local(cctx, func_name, name_end - name_start,
+ lvar = reserve_local(cctx, func_name, name_end - name_start,
TRUE, ufunc->uf_func_type);
-
if (lvar == NULL)
goto theend;
if (generate_FUNCREF(cctx, ufunc, &funcref_isn) == FAIL)
@@ -949,6 +949,9 @@ compile_nested_function(exarg_T *eap, cctx_T *cctx, garray_T *lines_to_free)
&& compile_def_function(ufunc, TRUE, compile_type, cctx) == FAIL)
{
func_ptr_unref(ufunc);
+ if (lvar != NULL)
+ // Now the local variable can't be used.
+ *lvar->lv_name = '/'; // impossible value
goto theend;
}
--
2.36.1

View File

@ -1,73 +0,0 @@
From 4875d6ab068f09df88d24d81de40dcd8d56e243d Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Wed, 17 Aug 2022 15:55:51 +0100
Subject: [PATCH] patch 9.0.0224: Using NULL pointer when skipping compiled
code
Problem: Using NULL pointer when skipping compiled code.
Solution: Check for skipping.
---
src/testdir/test_vim9_script.vim | 13 +++++++++++++
src/vim9compile.c | 14 ++++++++++----
2 files changed, 23 insertions(+), 4 deletions(-)
diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim
index fc0ef15..75b3e9c 100644
--- a/src/testdir/test_vim9_script.vim
+++ b/src/testdir/test_vim9_script.vim
@@ -2097,6 +2097,19 @@ def Test_for_skipped_block()
v9.CheckDefAndScriptSuccess(lines)
enddef
+def Test_skipped_redir()
+ var lines =<< trim END
+ def T()
+ if 0
+ redir =>l[0]
+ redir END
+ endif
+ enddef
+ defcompile
+ END
+ v9.CheckScriptSuccess(lines)
+enddef
+
def Test_for_loop()
var lines =<< trim END
var result = ''
diff --git a/src/vim9compile.c b/src/vim9compile.c
index fb39997..a8fa5dc 100644
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -1157,11 +1157,14 @@ generate_loadvar(
generate_LOADV(cctx, name + 2);
break;
case dest_local:
- if (lvar->lv_from_outer > 0)
- generate_LOADOUTER(cctx, lvar->lv_idx, lvar->lv_from_outer,
+ if (cctx->ctx_skip != SKIP_YES)
+ {
+ if (lvar->lv_from_outer > 0)
+ generate_LOADOUTER(cctx, lvar->lv_idx, lvar->lv_from_outer,
type);
- else
- generate_LOAD(cctx, ISN_LOAD, lvar->lv_idx, NULL, type);
+ else
+ generate_LOAD(cctx, ISN_LOAD, lvar->lv_idx, NULL, type);
+ }
break;
case dest_expr:
// list or dict value should already be on the stack.
@@ -1944,6 +1947,9 @@ compile_assign_unlet(
}
}
+ if (cctx->ctx_skip == SKIP_YES)
+ return OK;
+
// Load the dict or list. On the stack we then have:
// - value (for assignment, not for :unlet)
// - index
--
2.36.1

View File

@ -1,245 +0,0 @@
From 91c7cbfe31bbef57d5fcf7d76989fc159f73ef15 Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Thu, 18 Aug 2022 13:28:31 +0100
Subject: [PATCH] patch 9.0.0225: using freed memory with multiple line breaks
in expression
Problem: Using freed memory with multiple line breaks in expression.
Solution: Free eval_tofree later.
---
src/eval.c | 102 ++++++++++++++++++-------------
src/proto/eval.pro | 4 +-
src/testdir/test_vim9_script.vim | 13 ++++
src/userfunc.c | 15 -----
4 files changed, 75 insertions(+), 59 deletions(-)
diff --git a/src/eval.c b/src/eval.c
index 42b883e..60daca5 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -353,6 +353,63 @@ eval_to_string_skip(
return retval;
}
+/*
+ * Initialize "evalarg" for use.
+ */
+ void
+init_evalarg(evalarg_T *evalarg)
+{
+ CLEAR_POINTER(evalarg);
+ ga_init2(&evalarg->eval_tofree_ga, sizeof(char_u *), 20);
+}
+
+/*
+ * If "evalarg->eval_tofree" is not NULL free it later.
+ * Caller is expected to overwrite "evalarg->eval_tofree" next.
+ */
+ static void
+free_eval_tofree_later(evalarg_T *evalarg)
+{
+ if (evalarg->eval_tofree != NULL)
+ {
+ if (ga_grow(&evalarg->eval_tofree_ga, 1) == OK)
+ ((char_u **)evalarg->eval_tofree_ga.ga_data)
+ [evalarg->eval_tofree_ga.ga_len++]
+ = evalarg->eval_tofree;
+ else
+ vim_free(evalarg->eval_tofree);
+ }
+}
+
+/*
+ * After using "evalarg" filled from "eap": free the memory.
+ */
+ void
+clear_evalarg(evalarg_T *evalarg, exarg_T *eap)
+{
+ if (evalarg != NULL)
+ {
+ if (evalarg->eval_tofree != NULL)
+ {
+ if (eap != NULL)
+ {
+ // We may need to keep the original command line, e.g. for
+ // ":let" it has the variable names. But we may also need the
+ // new one, "nextcmd" points into it. Keep both.
+ vim_free(eap->cmdline_tofree);
+ eap->cmdline_tofree = *eap->cmdlinep;
+ *eap->cmdlinep = evalarg->eval_tofree;
+ }
+ else
+ vim_free(evalarg->eval_tofree);
+ evalarg->eval_tofree = NULL;
+ }
+
+ ga_clear_strings(&evalarg->eval_tofree_ga);
+ VIM_CLEAR(evalarg->eval_tofree_lambda);
+ }
+}
+
/*
* Skip over an expression at "*pp".
* Return FAIL for an error, OK otherwise.
@@ -435,8 +492,8 @@ skip_expr_concatenate(
// Do not free the first line, the caller can still use it.
*((char_u **)gap->ga_data) = NULL;
// Do not free the last line, "arg" points into it, free it
- // later.
- vim_free(evalarg->eval_tofree);
+ // later. Also free "eval_tofree" later if needed.
+ free_eval_tofree_later(evalarg);
evalarg->eval_tofree =
((char_u **)gap->ga_data)[gap->ga_len - 1];
((char_u **)gap->ga_data)[gap->ga_len - 1] = NULL;
@@ -2274,7 +2331,7 @@ eval_next_line(char_u *arg, evalarg_T *evalarg)
}
else if (evalarg->eval_cookie != NULL)
{
- vim_free(evalarg->eval_tofree);
+ free_eval_tofree_later(evalarg);
evalarg->eval_tofree = line;
}
@@ -2301,45 +2358,6 @@ skipwhite_and_linebreak(char_u *arg, evalarg_T *evalarg)
return p;
}
-/*
- * Initialize "evalarg" for use.
- */
- void
-init_evalarg(evalarg_T *evalarg)
-{
- CLEAR_POINTER(evalarg);
- ga_init2(&evalarg->eval_tofree_ga, sizeof(char_u *), 20);
-}
-
-/*
- * After using "evalarg" filled from "eap": free the memory.
- */
- void
-clear_evalarg(evalarg_T *evalarg, exarg_T *eap)
-{
- if (evalarg != NULL)
- {
- if (evalarg->eval_tofree != NULL)
- {
- if (eap != NULL)
- {
- // We may need to keep the original command line, e.g. for
- // ":let" it has the variable names. But we may also need the
- // new one, "nextcmd" points into it. Keep both.
- vim_free(eap->cmdline_tofree);
- eap->cmdline_tofree = *eap->cmdlinep;
- *eap->cmdlinep = evalarg->eval_tofree;
- }
- else
- vim_free(evalarg->eval_tofree);
- evalarg->eval_tofree = NULL;
- }
-
- ga_clear_strings(&evalarg->eval_tofree_ga);
- VIM_CLEAR(evalarg->eval_tofree_lambda);
- }
-}
-
/*
* The "evaluate" argument: When FALSE, the argument is only parsed but not
* executed. The function may return OK, but the rettv will be of type
diff --git a/src/proto/eval.pro b/src/proto/eval.pro
index e6cd892..27a13c9 100644
--- a/src/proto/eval.pro
+++ b/src/proto/eval.pro
@@ -9,6 +9,8 @@ int eval_expr_valid_arg(typval_T *tv);
int eval_expr_typval(typval_T *expr, typval_T *argv, int argc, typval_T *rettv);
int eval_expr_to_bool(typval_T *expr, int *error);
char_u *eval_to_string_skip(char_u *arg, exarg_T *eap, int skip);
+void init_evalarg(evalarg_T *evalarg);
+void clear_evalarg(evalarg_T *evalarg, exarg_T *eap);
int skip_expr(char_u **pp, evalarg_T *evalarg);
int skip_expr_concatenate(char_u **arg, char_u **start, char_u **end, evalarg_T *evalarg);
char_u *typval2string(typval_T *tv, int convert);
@@ -34,8 +36,6 @@ int pattern_match(char_u *pat, char_u *text, int ic);
char_u *eval_next_non_blank(char_u *arg, evalarg_T *evalarg, int *getnext);
char_u *eval_next_line(char_u *arg, evalarg_T *evalarg);
char_u *skipwhite_and_linebreak(char_u *arg, evalarg_T *evalarg);
-void init_evalarg(evalarg_T *evalarg);
-void clear_evalarg(evalarg_T *evalarg, exarg_T *eap);
int eval0(char_u *arg, typval_T *rettv, exarg_T *eap, evalarg_T *evalarg);
int eval0_retarg(char_u *arg, typval_T *rettv, exarg_T *eap, evalarg_T *evalarg, char_u **retarg);
int eval1(char_u **arg, typval_T *rettv, evalarg_T *evalarg);
diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim
index 75b3e9c..c09c0d2 100644
--- a/src/testdir/test_vim9_script.vim
+++ b/src/testdir/test_vim9_script.vim
@@ -1560,6 +1560,19 @@ def Test_func_redefine_fails()
v9.CheckScriptFailure(lines, 'E1073:')
enddef
+def Test_lambda_split()
+ # this was using freed memory, because of the split expression
+ var lines =<< trim END
+ vim9script
+ try
+ 0
+ 0->(0
+ ->a.0(
+ ->u
+ END
+ v9.CheckScriptFailure(lines, 'E1050:')
+enddef
+
def Test_fixed_size_list()
# will be allocated as one piece of memory, check that changes work
var l = [1, 2, 3, 4]
diff --git a/src/userfunc.c b/src/userfunc.c
index 9b960b7..3777e03 100644
--- a/src/userfunc.c
+++ b/src/userfunc.c
@@ -1371,7 +1371,6 @@ get_lambda_tv(
char_u *start, *end;
int *old_eval_lavars = eval_lavars_used;
int eval_lavars = FALSE;
- char_u *tofree1 = NULL;
char_u *tofree2 = NULL;
int equal_arrow = **arg == '(';
int white_error = FALSE;
@@ -1456,12 +1455,6 @@ get_lambda_tv(
ret = skip_expr_concatenate(arg, &start, &end, evalarg);
if (ret == FAIL)
goto errret;
- if (evalarg != NULL)
- {
- // avoid that the expression gets freed when another line break follows
- tofree1 = evalarg->eval_tofree;
- evalarg->eval_tofree = NULL;
- }
if (!equal_arrow)
{
@@ -1584,10 +1577,6 @@ get_lambda_tv(
theend:
eval_lavars_used = old_eval_lavars;
- if (evalarg != NULL && evalarg->eval_tofree == NULL)
- evalarg->eval_tofree = tofree1;
- else
- vim_free(tofree1);
vim_free(tofree2);
if (types_optional)
ga_clear_strings(&argtypes);
@@ -1606,10 +1595,6 @@ errret:
}
vim_free(fp);
vim_free(pt);
- if (evalarg != NULL && evalarg->eval_tofree == NULL)
- evalarg->eval_tofree = tofree1;
- else
- vim_free(tofree1);
vim_free(tofree2);
eval_lavars_used = old_eval_lavars;
return FAIL;
--
2.36.1

View File

@ -1,56 +0,0 @@
From 6669de1b235843968e88844ca6d3c8dec4b01a9e Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Sun, 21 Aug 2022 20:33:47 +0100
Subject: [PATCH] patch 9.0.0240: crash when using ":mkspell" with an
empty
.dic file
Problem: Crash when using ":mkspell" with an empty .dic file.
Solution: Check for an empty word tree.
---
src/spellfile.c | 4 +++-
src/testdir/test_spellfile.vim | 12 ++++++++++++
2 files changed, 15 insertions(+), 1 deletion(-)
diff --git a/src/spellfile.c b/src/spellfile.c
index 4a0de52..a4407fa 100644
--- a/src/spellfile.c
+++ b/src/spellfile.c
@@ -5585,10 +5585,12 @@ sug_filltree(spellinfo_T *spin, slang_T *slang)
/*
* Go through the whole case-folded tree, soundfold each word and put it
- * in the trie.
+ * in the trie. Bail out if the tree is empty.
*/
byts = slang->sl_fbyts;
idxs = slang->sl_fidxs;
+ if (byts == NULL || idxs == NULL)
+ return FAIL;
arridx[0] = 0;
curi[0] = 1;
diff --git a/src/testdir/test_spellfile.vim b/src/testdir/test_spellfile.vim
index 38d1ec0..e81aa65 100644
--- a/src/testdir/test_spellfile.vim
+++ b/src/testdir/test_spellfile.vim
@@ -1160,4 +1160,16 @@ func Test_mkspellmem_opt()
call assert_fails('set mkspellmem=1000,50,0', 'E474:')
endfunc
+" this was using a NULL pointer
+func Test_mkspell_empty_dic()
+ call writefile(['1'], 'XtestEmpty.dic')
+ call writefile(['SOFOFROM abcd', 'SOFOTO ABCD', 'SAL CIA X'], 'XtestEmpty.aff')
+ mkspell! XtestEmpty.spl XtestEmpty
+
+ call delete('XtestEmpty.dic')
+ call delete('XtestEmpty.aff')
+ call delete('XtestEmpty.spl')
+endfunc
+
+
" vim: shiftwidth=2 sts=2 expandtab
--
2.36.1

View File

@ -1,71 +0,0 @@
From adce965162dd89bf29ee0e5baf53652e7515762c Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Mon, 22 Aug 2022 16:35:45 +0100
Subject: [PATCH] patch 9.0.0246: using freed memory when 'tagfunc' deletes the
buffer
Problem: Using freed memory when 'tagfunc' deletes the buffer.
Solution: Make a copy of the tag name.
---
src/tag.c | 9 ++++++++-
src/testdir/test_tagfunc.vim | 12 ++++++++++++
2 files changed, 20 insertions(+), 1 deletion(-)
diff --git a/src/tag.c b/src/tag.c
index 8a351cc..02f0818 100644
--- a/src/tag.c
+++ b/src/tag.c
@@ -281,6 +281,7 @@ do_tag(
char_u *buf_ffname = curbuf->b_ffname; // name to use for
// priority computation
int use_tfu = 1;
+ char_u *tofree = NULL;
// remember the matches for the last used tag
static int num_matches = 0;
@@ -630,7 +631,12 @@ do_tag(
* When desired match not found yet, try to find it (and others).
*/
if (use_tagstack)
- name = tagstack[tagstackidx].tagname;
+ {
+ // make a copy, the tagstack may change in 'tagfunc'
+ name = vim_strsave(tagstack[tagstackidx].tagname);
+ vim_free(tofree);
+ tofree = name;
+ }
#if defined(FEAT_QUICKFIX)
else if (g_do_tagpreview != 0)
name = ptag_entry.tagname;
@@ -922,6 +928,7 @@ end_do_tag:
g_do_tagpreview = 0; // don't do tag preview next time
# endif
+ vim_free(tofree);
#ifdef FEAT_CSCOPE
return jumped_to_tag;
#else
diff --git a/src/testdir/test_tagfunc.vim b/src/testdir/test_tagfunc.vim
index 05d8473..9582612 100644
--- a/src/testdir/test_tagfunc.vim
+++ b/src/testdir/test_tagfunc.vim
@@ -389,4 +389,16 @@ func Test_tagfunc_callback()
%bw!
endfunc
+func Test_tagfunc_wipes_buffer()
+ func g:Tag0unc0(t,f,o)
+ bwipe
+ endfunc
+ set tagfunc=g:Tag0unc0
+ new
+ cal assert_fails('tag 0', 'E987:')
+
+ delfunc g:Tag0unc0
+ set tagfunc=
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
--
1.8.3.1

View File

@ -1,172 +0,0 @@
From 80525751c5ce9ed82c41d83faf9ef38667bf61b1 Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Wed, 24 Aug 2022 19:27:45 +0100
Subject: [PATCH] patch 9.0.0259: crash with mouse click when not initialized
Problem: Crash with mouse click when not initialized.
Solution: Check TabPageIdxs[] is not NULL.
---
src/mouse.c | 107 ++++++++++++++++++++++---------------------
src/testdir/test_tabline.vim | 14 ++++++
2 files changed, 69 insertions(+), 52 deletions(-)
diff --git a/src/mouse.c b/src/mouse.c
index c39f614..12895f8 100644
--- a/src/mouse.c
+++ b/src/mouse.c
@@ -471,74 +471,77 @@ do_mouse(
start_visual.lnum = 0;
- // Check for clicking in the tab page line.
- if (mouse_row == 0 && firstwin->w_winrow > 0)
+ if (TabPageIdxs != NULL) // only when initialized
{
- if (is_drag)
+ // Check for clicking in the tab page line.
+ if (mouse_row == 0 && firstwin->w_winrow > 0)
{
- if (in_tab_line)
+ if (is_drag)
{
- c1 = TabPageIdxs[mouse_col];
- tabpage_move(c1 <= 0 ? 9999 : c1 < tabpage_index(curtab)
- ? c1 - 1 : c1);
+ if (in_tab_line)
+ {
+ c1 = TabPageIdxs[mouse_col];
+ tabpage_move(c1 <= 0 ? 9999 : c1 < tabpage_index(curtab)
+ ? c1 - 1 : c1);
+ }
+ return FALSE;
}
- return FALSE;
- }
- // click in a tab selects that tab page
- if (is_click
+ // click in a tab selects that tab page
+ if (is_click
# ifdef FEAT_CMDWIN
- && cmdwin_type == 0
+ && cmdwin_type == 0
# endif
- && mouse_col < Columns)
- {
- in_tab_line = TRUE;
- c1 = TabPageIdxs[mouse_col];
- if (c1 >= 0)
+ && mouse_col < Columns)
{
- if ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_2CLICK)
- {
- // double click opens new page
- end_visual_mode_keep_button();
- tabpage_new();
- tabpage_move(c1 == 0 ? 9999 : c1 - 1);
- }
- else
+ in_tab_line = TRUE;
+ c1 = TabPageIdxs[mouse_col];
+ if (c1 >= 0)
{
- // Go to specified tab page, or next one if not clicking
- // on a label.
- goto_tabpage(c1);
-
- // It's like clicking on the status line of a window.
- if (curwin != old_curwin)
+ if ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_2CLICK)
+ {
+ // double click opens new page
end_visual_mode_keep_button();
- }
- }
- else
- {
- tabpage_T *tp;
+ tabpage_new();
+ tabpage_move(c1 == 0 ? 9999 : c1 - 1);
+ }
+ else
+ {
+ // Go to specified tab page, or next one if not clicking
+ // on a label.
+ goto_tabpage(c1);
- // Close the current or specified tab page.
- if (c1 == -999)
- tp = curtab;
+ // It's like clicking on the status line of a window.
+ if (curwin != old_curwin)
+ end_visual_mode_keep_button();
+ }
+ }
else
- tp = find_tabpage(-c1);
- if (tp == curtab)
{
- if (first_tabpage->tp_next != NULL)
- tabpage_close(FALSE);
+ tabpage_T *tp;
+
+ // Close the current or specified tab page.
+ if (c1 == -999)
+ tp = curtab;
+ else
+ tp = find_tabpage(-c1);
+ if (tp == curtab)
+ {
+ if (first_tabpage->tp_next != NULL)
+ tabpage_close(FALSE);
+ }
+ else if (tp != NULL)
+ tabpage_close_other(tp, FALSE);
}
- else if (tp != NULL)
- tabpage_close_other(tp, FALSE);
}
+ return TRUE;
+ }
+ else if (is_drag && in_tab_line)
+ {
+ c1 = TabPageIdxs[mouse_col];
+ tabpage_move(c1 <= 0 ? 9999 : c1 - 1);
+ return FALSE;
}
- return TRUE;
- }
- else if (is_drag && in_tab_line)
- {
- c1 = TabPageIdxs[mouse_col];
- tabpage_move(c1 <= 0 ? 9999 : c1 - 1);
- return FALSE;
}
// When 'mousemodel' is "popup" or "popup_setpos", translate mouse events:
diff --git a/src/testdir/test_tabline.vim b/src/testdir/test_tabline.vim
index e58a412..556b859 100644
--- a/src/testdir/test_tabline.vim
+++ b/src/testdir/test_tabline.vim
@@ -147,4 +147,18 @@ func Test_tabline_20_format_items_no_overrun()
set showtabline& tabline&
endfunc
+func Test_mouse_click_in_tab()
+ " This used to crash because TabPageIdxs[] was not initialized
+ let lines =<< trim END
+ tabnew
+ set mouse=a
+ exe "norm \<LeftMouse>"
+ END
+ call writefile(lines, 'Xclickscript')
+ call RunVim([], [], "-e -s -S Xclickscript -c qa")
+
+ call delete('Xclickscript')
+endfunc
+
+
" vim: shiftwidth=2 sts=2 expandtab
--
1.8.3.1

View File

@ -1,73 +0,0 @@
From d6c67629ed05aae436164eec474832daf8ba7420 Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Wed, 24 Aug 2022 20:07:22 +0100
Subject: [PATCH] patch 9.0.0260: using freed memory when usinger
'quickfixtextfunc' recursivelyxe
Problem: Using freed memory when using 'quickfixtextfunc' recursively.
Solution: Do not allow for recursion.
---
src/quickfix.c | 9 +++++++++
src/testdir/test_quickfix.vim | 13 +++++++++++++
2 files changed, 22 insertions(+)
diff --git a/src/quickfix.c b/src/quickfix.c
index c37caa5..5547233 100644
--- a/src/quickfix.c
+++ b/src/quickfix.c
@@ -4656,6 +4656,11 @@ call_qftf_func(qf_list_T *qfl, int qf_winid, long start_idx, long end_idx)
{
callback_T *cb = &qftf_cb;
list_T *qftf_list = NULL;
+ static int recursive = FALSE;
+
+ if (recursive)
+ return NULL; // this doesn't work properly recursively
+ recursive = TRUE;
// If 'quickfixtextfunc' is set, then use the user-supplied function to get
// the text to display. Use the local value of 'quickfixtextfunc' if it is
@@ -4670,7 +4675,10 @@ call_qftf_func(qf_list_T *qfl, int qf_winid, long start_idx, long end_idx)
// create the dict argument
if ((d = dict_alloc_lock(VAR_FIXED)) == NULL)
+ {
+ recursive = FALSE;
return NULL;
+ }
dict_add_number(d, "quickfix", (long)IS_QF_LIST(qfl));
dict_add_number(d, "winid", (long)qf_winid);
dict_add_number(d, "id", (long)qfl->qf_id);
@@ -4693,6 +4701,7 @@ call_qftf_func(qf_list_T *qfl, int qf_winid, long start_idx, long end_idx)
dict_unref(d);
}
+ recursive = FALSE;
return qftf_list;
}
diff --git a/src/testdir/test_quickfix.vim b/src/testdir/test_quickfix.vim
index 182d570..46b2cb6 100644
--- a/src/testdir/test_quickfix.vim
+++ b/src/testdir/test_quickfix.vim
@@ -6334,4 +6334,17 @@ func Test_qflist_statusmsg()
%bw!
endfunc
+func Test_quickfixtextfunc_recursive()
+ func s:QFTfunc(o)
+ cgete '0'
+ endfunc
+ copen
+ let &quickfixtextfunc = 's:QFTfunc'
+ cex ""
+
+ let &quickfixtextfunc = ''
+ cclose
+endfunc
+
+
" vim: shiftwidth=2 sts=2 expandtab
--
2.36.1

View File

@ -1,151 +0,0 @@
From 6d24a51b94beb1991cddce221f90b455e2d50db7 Mon Sep 17 00:00:00 2001
From: Yegappan Lakshmanan <yegappan@yahoo.com>
Date: Sat, 27 Aug 2022 20:59:57 +0100
Subject: [PATCH] patch 9.0.0286: using freed memory when location list changed
in autocmd
Problem: Using freed memory when location list changed in autocmd.
Solution: Return QF_ABORT and handle it. (Yegappan Lakshmanan,
closes #10993)
---
src/quickfix.c | 28 ++++++++++++++++++----------
src/testdir/test_quickfix.vim | 17 +++++++++++++++++
2 files changed, 35 insertions(+), 10 deletions(-)
diff --git a/src/quickfix.c b/src/quickfix.c
index 6af62e8..78f6880 100644
--- a/src/quickfix.c
+++ b/src/quickfix.c
@@ -594,6 +594,7 @@ enum {
QF_NOMEM = 3,
QF_IGNORE_LINE = 4,
QF_MULTISCAN = 5,
+ QF_ABORT = 6
};
/*
@@ -3153,7 +3154,7 @@ qf_jump_to_usable_window(int qf_fnum, int newwin, int *opened_window)
/*
* Edit the selected file or help file.
* Returns OK if successfully edited the file, FAIL on failing to open the
- * buffer and NOTDONE if the quickfix/location list was freed by an autocmd
+ * buffer and QF_ABORT if the quickfix/location list was freed by an autocmd
* when opening the buffer.
*/
static int
@@ -3199,14 +3200,14 @@ qf_jump_edit_buffer(
{
emsg(_(e_current_window_was_closed));
*opened_window = FALSE;
- return NOTDONE;
+ return QF_ABORT;
}
}
if (qfl_type == QFLT_QUICKFIX && !qflist_valid(NULL, save_qfid))
{
emsg(_(e_current_quickfix_list_was_changed));
- return NOTDONE;
+ return QF_ABORT;
}
// Check if the list was changed. The pointers may happen to be identical,
@@ -3219,7 +3220,7 @@ qf_jump_edit_buffer(
emsg(_(e_current_quickfix_list_was_changed));
else
emsg(_(e_current_location_list_was_changed));
- return NOTDONE;
+ return QF_ABORT;
}
return retval;
@@ -3317,7 +3318,8 @@ qf_jump_print_msg(
* a new window.
* Returns OK if successfully jumped or opened a window. Returns FAIL if not
* able to jump/open a window. Returns NOTDONE if a file is not associated
- * with the entry.
+ * with the entry. Returns QF_ABORT if the quickfix/location list was modified
+ * by an autocmd.
*/
static int
qf_jump_open_window(
@@ -3344,7 +3346,7 @@ qf_jump_open_window(
emsg(_(e_current_quickfix_list_was_changed));
else
emsg(_(e_current_location_list_was_changed));
- return FAIL;
+ return QF_ABORT;
}
// If currently in the quickfix window, find another window to show the
@@ -3368,7 +3370,7 @@ qf_jump_open_window(
emsg(_(e_current_quickfix_list_was_changed));
else
emsg(_(e_current_location_list_was_changed));
- return FAIL;
+ return QF_ABORT;
}
return OK;
@@ -3379,7 +3381,7 @@ qf_jump_open_window(
* particular line/column, adjust the folds and display a message about the
* jump.
* Returns OK on success and FAIL on failing to open the file/buffer. Returns
- * NOTDONE if the quickfix/location list is freed by an autocmd when opening
+ * QF_ABORT if the quickfix/location list is freed by an autocmd when opening
* the file.
*/
static int
@@ -3508,14 +3510,20 @@ qf_jump_newwin(qf_info_T *qi,
retval = qf_jump_open_window(qi, qf_ptr, newwin, &opened_window);
if (retval == FAIL)
goto failed;
+ if (retval == QF_ABORT)
+ {
+ qi = NULL;
+ qf_ptr = NULL;
+ goto theend;
+ }
if (retval == NOTDONE)
goto theend;
retval = qf_jump_to_buffer(qi, qf_index, qf_ptr, forceit, prev_winid,
&opened_window, old_KeyTyped, print_message);
- if (retval == NOTDONE)
+ if (retval == QF_ABORT)
{
- // Quickfix/location list is freed by an autocmd
+ // Quickfix/location list was modified by an autocmd
qi = NULL;
qf_ptr = NULL;
}
diff --git a/src/testdir/test_quickfix.vim b/src/testdir/test_quickfix.vim
index 762fa8d..31d36ef 100644
--- a/src/testdir/test_quickfix.vim
+++ b/src/testdir/test_quickfix.vim
@@ -6363,5 +6363,22 @@ func Test_quickfixtextfunc_recursive()
cclose
endfunc
+" Test for replacing the location list from an autocmd. This used to cause a
+" read from freed memory.
+func Test_loclist_replace_autocmd()
+ %bw!
+ call setloclist(0, [], 'f')
+ let s:bufnr = bufnr()
+ cal setloclist(0, [{'0': 0, '': ''}])
+ au BufEnter * cal setloclist(1, [{'t': ''}, {'bufnr': s:bufnr}], 'r')
+ lopen
+ try
+ exe "norm j\<CR>"
+ catch
+ endtry
+ lnext
+ %bw!
+ call setloclist(0, [], 'f')
+endfunc
" vim: shiftwidth=2 sts=2 expandtab
--
1.8.3.1

View File

@ -1,56 +0,0 @@
From 4f1b083be43f351bc107541e7b0c9655a5d2c0bb Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Mon, 29 Aug 2022 20:45:16 +0100
Subject: [PATCH] patch 9.0.0322: crash when no errors and 'quickfixtextfunc'
is set
Problem: Crash when no errors and 'quickfixtextfunc' is set.
Solution: Do not handle errors if there aren't any.
---
src/quickfix.c | 2 +-
src/testdir/test_quickfix.vim | 16 ++++++++++++++++
2 files changed, 17 insertions(+), 1 deletion(-)
diff --git a/src/quickfix.c b/src/quickfix.c
index f6851ef..edf262c 100644
--- a/src/quickfix.c
+++ b/src/quickfix.c
@@ -4743,7 +4743,7 @@ qf_fill_buffer(qf_list_T *qfl, buf_T *buf, qfline_T *old_last, int qf_winid)
}
// Check if there is anything to display
- if (qfl != NULL)
+ if (qfl != NULL && qfl->qf_start != NULL)
{
char_u dirname[MAXPATHL];
int invalid_val = FALSE;
diff --git a/src/testdir/test_quickfix.vim b/src/testdir/test_quickfix.vim
index cf803ca..27bed51 100644
--- a/src/testdir/test_quickfix.vim
+++ b/src/testdir/test_quickfix.vim
@@ -4090,6 +4090,22 @@ func Xgetlist_empty_tests(cchar)
endif
endfunc
+func Test_empty_list_quickfixtextfunc()
+ " This was crashing. Can only reproduce by running it in a separate Vim
+ " instance.
+ let lines =<< trim END
+ func s:Func(o)
+ cgetexpr '0'
+ endfunc
+ cope
+ let &quickfixtextfunc = 's:Func'
+ cgetfile [ex
+ END
+ call writefile(lines, 'Xquickfixtextfunc')
+ call RunVim([], [], '-e -s -S Xquickfixtextfunc -c qa')
+ call delete('Xquickfixtextfunc')
+endfunc
+
func Test_getqflist()
call Xgetlist_empty_tests('c')
call Xgetlist_empty_tests('l')
--
2.33.0

Binary file not shown.

View File

@ -1,69 +0,0 @@
From ccfde4d028e891a41e3548323c3d47b06fb0b83e Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Mon, 5 Sep 2022 19:51:13 +0100
Subject: [PATCH] patch 9.0.0389: crash when 'tagfunc' closes the window
Problem: Crash when 'tagfunc' closes the window.
Solution: Bail out when the window was closed.
---
src/errors.h | 2 ++
src/tag.c | 10 ++++++++++
src/testdir/test_tagfunc.vim | 12 ++++++++++++
3 files changed, 24 insertions(+)
diff --git a/src/errors.h b/src/errors.h
index 43a1c9b..bfb4ae8 100644
--- a/src/errors.h
+++ b/src/errors.h
@@ -3304,3 +3304,5 @@ EXTERN char e_could_not_check_for_pending_sigalrm_str[]
EXTERN char e_substitute_nesting_too_deep[]
INIT(= N_("E1290: substitute nesting too deep"));
#endif
+EXTERN char e_window_unexpectedly_close_while_searching_for_tags[]
+ INIT(= N_("E1299: Window unexpectedly closed while searching for tags"));
diff --git a/src/tag.c b/src/tag.c
index 8edb0c7..b4915cb 100644
--- a/src/tag.c
+++ b/src/tag.c
@@ -690,6 +690,16 @@ do_tag(
max_num_matches = MAXCOL; // If less than max_num_matches
// found: all matches found.
+ // A tag function may do anything, which may cause various
+ // information to become invalid. At least check for the tagstack
+ // to still be the same.
+ if (tagstack != curwin->w_tagstack)
+ {
+ emsg(_(e_window_unexpectedly_close_while_searching_for_tags));
+ FreeWild(new_num_matches, new_matches);
+ break;
+ }
+
// If there already were some matches for the same name, move them
// to the start. Avoids that the order changes when using
// ":tnext" and jumping to another file.
diff --git a/src/testdir/test_tagfunc.vim b/src/testdir/test_tagfunc.vim
index 9582612..c10a82d 100644
--- a/src/testdir/test_tagfunc.vim
+++ b/src/testdir/test_tagfunc.vim
@@ -401,4 +401,16 @@ func Test_tagfunc_wipes_buffer()
set tagfunc=
endfunc
+func Test_tagfunc_closes_window()
+ split any
+ func MytagfuncClose(pat, flags, info)
+ close
+ return [{'name' : 'mytag', 'filename' : 'Xtest', 'cmd' : '1'}]
+ endfunc
+ set tagfunc=MytagfuncClose
+ call assert_fails('tag xyz', 'E1299:')
+
+ set tagfunc=
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
--
2.33.0

View File

@ -1,87 +0,0 @@
From 1540d334a04d874c2aa9d26b82dbbcd4bc5a78de Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Wed, 7 Sep 2022 15:20:26 +0100
Subject: [PATCH] patch 9.0.0404: crash when passing invalid arguments to
assert_fails()
Problem: Crash when passing invalid arguments to assert_fails().
Solution: Check for NULL string.
---
src/testdir/test_assert.vim | 19 +++++++++++++++++--
src/testing.c | 9 +++++++++
2 files changed, 26 insertions(+), 2 deletions(-)
diff --git a/src/testdir/test_assert.vim b/src/testdir/test_assert.vim
index 7c9d090..9d8a018 100644
--- a/src/testdir/test_assert.vim
+++ b/src/testdir/test_assert.vim
@@ -278,6 +278,21 @@ func Test_assert_fail_fails()
endtry
call assert_match("E1222: String or List required for argument 2", exp)
+ try
+ call assert_equal(0, assert_fails('xxx', [#{one: 1}]))
+ catch
+ let exp = v:exception
+ endtry
+ call assert_match("E731: Using a Dictionary as a String", exp)
+
+ let exp = ''
+ try
+ call assert_equal(0, assert_fails('xxx', ['E492', #{one: 1}]))
+ catch
+ let exp = v:exception
+ endtry
+ call assert_match("E731: Using a Dictionary as a String", exp)
+
try
call assert_equal(1, assert_fails('xxx', 'E492', '', 'burp'))
catch
@@ -292,8 +307,8 @@ func Test_assert_fail_fails()
endtry
call assert_match("E1174: String required for argument 5", exp)
- call assert_equal(1, assert_fails('c0', ['', '\1']))
- call assert_match("Expected '\\\\\\\\1' but got 'E939: Positive count required: c0': c0", v:errors[0])
+ call assert_equal(1, assert_fails('c0', ['', '\(.\)\1']))
+ call assert_match("Expected '\\\\\\\\(.\\\\\\\\)\\\\\\\\1' but got 'E939: Positive count required: c0': c0", v:errors[0])
call remove(v:errors, 0)
endfunc
diff --git a/src/testing.c b/src/testing.c
index 43b8d20..b4c4ff4 100644
--- a/src/testing.c
+++ b/src/testing.c
@@ -616,6 +616,11 @@ f_assert_fails(typval_T *argvars, typval_T *rettv)
in_assert_fails = TRUE;
do_cmdline_cmd(cmd);
+
+ // reset here for any errors reported below
+ trylevel = save_trylevel;
+ suppress_errthrow = FALSE;
+
if (called_emsg == called_emsg_before)
{
prepare_assert_error(&ga);
@@ -654,6 +659,8 @@ f_assert_fails(typval_T *argvars, typval_T *rettv)
CHECK_LIST_MATERIALIZE(list);
tv = &list->lv_first->li_tv;
expected = tv_get_string_buf_chk(tv, buf);
+ if (expected == NULL)
+ goto theend;
if (!pattern_match(expected, actual, FALSE))
{
error_found = TRUE;
@@ -667,6 +674,8 @@ f_assert_fails(typval_T *argvars, typval_T *rettv)
{
tv = &list->lv_u.mat.lv_last->li_tv;
expected = tv_get_string_buf_chk(tv, buf);
+ if (expected == NULL)
+ goto theend;
if (!pattern_match(expected, actual, FALSE))
{
error_found = TRUE;
--
2.27.0

View File

@ -1,78 +0,0 @@
From c249913edc35c0e666d783bfc21595cf9f7d9e0d Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Fri, 16 Sep 2022 22:16:59 +0100
Subject: [PATCH] patch 9.0.0483: illegal memory access when replacing in
virtualedit mode
Problem: Illegal memory access when replacing in virtualedit mode.
Solution: Check for replacing NUL after Tab.
---
src/ops.c | 12 ++++++++++--
src/testdir/test_virtualedit.vim | 14 ++++++++++++++
2 files changed, 24 insertions(+), 2 deletions(-)
diff --git a/src/ops.c b/src/ops.c
index b930878..33cbd8e 100644
--- a/src/ops.c
+++ b/src/ops.c
@@ -1160,6 +1160,8 @@ op_replace(oparg_T *oap, int c)
while (LTOREQ_POS(curwin->w_cursor, oap->end))
{
+ int done = FALSE;
+
n = gchar_cursor();
if (n != NUL)
{
@@ -1173,6 +1175,7 @@ op_replace(oparg_T *oap, int c)
if (curwin->w_cursor.lnum == oap->end.lnum)
oap->end.col += new_byte_len - old_byte_len;
replace_character(c);
+ done = TRUE;
}
else
{
@@ -1191,10 +1194,15 @@ op_replace(oparg_T *oap, int c)
if (curwin->w_cursor.lnum == oap->end.lnum)
getvpos(&oap->end, end_vcol);
}
- PBYTE(curwin->w_cursor, c);
+ // with "coladd" set may move to just after a TAB
+ if (gchar_cursor() != NUL)
+ {
+ PBYTE(curwin->w_cursor, c);
+ done = TRUE;
+ }
}
}
- else if (virtual_op && curwin->w_cursor.lnum == oap->end.lnum)
+ if (!done && virtual_op && curwin->w_cursor.lnum == oap->end.lnum)
{
int virtcols = oap->end.coladd;
diff --git a/src/testdir/test_virtualedit.vim b/src/testdir/test_virtualedit.vim
index b31f3a2..0031b22 100644
--- a/src/testdir/test_virtualedit.vim
+++ b/src/testdir/test_virtualedit.vim
@@ -537,4 +537,18 @@ func Test_global_local_virtualedit()
set virtualedit&
endfunc
+" this was replacing the NUL at the end of the line
+func Test_virtualedit_replace_after_tab()
+ new
+ s/\v/ 0
+ set ve=all
+ let @" = ''
+ sil! norm vPvr0
+
+ call assert_equal("\t0", getline(1))
+ set ve&
+ bwipe!
+endfunc
+
+
" vim: shiftwidth=2 sts=2 expandtab
--
2.27.0

View File

@ -1,75 +0,0 @@
From 1c3dd8ddcba63c1af5112e567215b3cec2de11d0 Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Sat, 17 Sep 2022 19:43:23 +0100
Subject: [PATCH] patch 9.0.0490: using freed memory with cmdwin and BufEnter
autocmd
Problem: Using freed memory with cmdwin and BufEnter autocmd.
Solution: Make sure pointer to b_p_iminsert is still valid.
---
src/ex_getln.c | 8 ++++++--
src/testdir/test_cmdline.vim | 10 ++++++++++
2 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/src/ex_getln.c b/src/ex_getln.c
index 8dc03dc..535bfb5 100644
--- a/src/ex_getln.c
+++ b/src/ex_getln.c
@@ -1607,6 +1607,7 @@ getcmdline_int(
#endif
expand_T xpc;
long *b_im_ptr = NULL;
+ buf_T *b_im_ptr_buf = NULL; // buffer where b_im_ptr is valid
cmdline_info_T save_ccline;
int did_save_ccline = FALSE;
int cmdline_type;
@@ -1703,6 +1704,7 @@ getcmdline_int(
b_im_ptr = &curbuf->b_p_iminsert;
else
b_im_ptr = &curbuf->b_p_imsearch;
+ b_im_ptr_buf = curbuf;
if (*b_im_ptr == B_IMODE_LMAP)
State |= MODE_LANGMAP;
#ifdef HAVE_INPUT_METHOD
@@ -2060,7 +2062,8 @@ getcmdline_int(
goto cmdline_not_changed;
case Ctrl_HAT:
- cmdline_toggle_langmap(b_im_ptr);
+ cmdline_toggle_langmap(
+ buf_valid(b_im_ptr_buf) ? b_im_ptr : NULL);
goto cmdline_not_changed;
// case '@': only in very old vi
@@ -2573,7 +2576,8 @@ returncmd:
#endif
#ifdef HAVE_INPUT_METHOD
- if (b_im_ptr != NULL && *b_im_ptr != B_IMODE_LMAP)
+ if (b_im_ptr != NULL && buf_valid(b_im_ptr_buf)
+ && *b_im_ptr != B_IMODE_LMAP)
im_save_status(b_im_ptr);
im_set_active(FALSE);
#endif
diff --git a/src/testdir/test_cmdline.vim b/src/testdir/test_cmdline.vim
index 08e2de7..440df96 100644
--- a/src/testdir/test_cmdline.vim
+++ b/src/testdir/test_cmdline.vim
@@ -3447,4 +3447,14 @@ func Test_cmdwin_virtual_edit()
set ve= cpo-=$
endfunc
+" This was using a pointer to a freed buffer
+func Test_cmdwin_freed_buffer_ptr()
+ au BufEnter * next 0| file
+ edit 0
+ silent! norm q/
+
+ au! BufEnter
+ bwipe!
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
--
2.27.0

View File

@ -1,66 +0,0 @@
From 8ecfa2c56b4992c7f067b92488aa9acea5a454ad Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Wed, 21 Sep 2022 13:07:22 +0100
Subject: [PATCH] patch 9.0.0530: using freed memory when autocmd changes mark
Problem: Using freed memory when autocmd changes mark.
Solution: Copy the mark before editing another buffer.
---
src/mark.c | 12 +++++++-----
src/testdir/test_marks.vim | 13 +++++++++++++
2 files changed, 20 insertions(+), 5 deletions(-)
diff --git a/src/mark.c b/src/mark.c
index ade5a10..584db03 100644
--- a/src/mark.c
+++ b/src/mark.c
@@ -221,17 +221,19 @@ movemark(int count)
fname2fnum(jmp);
if (jmp->fmark.fnum != curbuf->b_fnum)
{
- // jump to other file
- if (buflist_findnr(jmp->fmark.fnum) == NULL)
+ // Make a copy, an autocommand may make "jmp" invalid.
+ fmark_T fmark = jmp->fmark;
+
+ // jump to the file with the mark
+ if (buflist_findnr(fmark.fnum) == NULL)
{ // Skip this one ..
count += count < 0 ? -1 : 1;
continue;
}
- if (buflist_getfile(jmp->fmark.fnum, jmp->fmark.mark.lnum,
- 0, FALSE) == FAIL)
+ if (buflist_getfile(fmark.fnum, fmark.mark.lnum, 0, FALSE) == FAIL)
return (pos_T *)NULL;
// Set lnum again, autocommands my have changed it
- curwin->w_cursor = jmp->fmark.mark;
+ curwin->w_cursor = fmark.mark;
pos = (pos_T *)-1;
}
else
diff --git a/src/testdir/test_marks.vim b/src/testdir/test_marks.vim
index 12501a3..20fb304 100644
--- a/src/testdir/test_marks.vim
+++ b/src/testdir/test_marks.vim
@@ -305,4 +305,17 @@ func Test_getmarklist()
close!
endfunc
+" This was using freed memory
+func Test_jump_mark_autocmd()
+ next 00
+ edit 0
+ sargument
+ au BufEnter 0 all
+ sil norm 
+
+ au! BufEnter
+ bwipe!
+endfunc
+
+
" vim: shiftwidth=2 sts=2 expandtab
--
2.27.0

View File

@ -1,56 +0,0 @@
From 69082916c8b5d321545d60b9f5facad0a2dd5a4e Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Thu, 22 Sep 2022 21:35:19 +0100
Subject: [PATCH] patch 9.0.0552: crash when using NUL in buffer that uses
:source
Problem: Crash when using NUL in buffer that uses :source.
Solution: Don't get a next line when skipping over NL.
---
src/eval.c | 2 +-
src/testdir/test_source.vim | 17 +++++++++++++++++
2 files changed, 18 insertions(+), 1 deletion(-)
diff --git a/src/eval.c b/src/eval.c
index 60daca5..8df374a 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -2278,7 +2278,7 @@ eval_next_non_blank(char_u *arg, evalarg_T *evalarg, int *getnext)
if (next != NULL)
{
- *getnext = TRUE;
+ *getnext = *p != NL;
return skipwhite(next);
}
}
diff --git a/src/testdir/test_source.vim b/src/testdir/test_source.vim
index 4736e93..d6aed57 100644
--- a/src/testdir/test_source.vim
+++ b/src/testdir/test_source.vim
@@ -665,5 +665,22 @@ func Test_source_buffer_long_line()
call delete('Xtest.vim')
endfunc
+func Test_source_buffer_with_NUL_char()
+ " This was trying to use a line below the buffer.
+ let lines =<< trim END
+ if !exists('g:loaded')
+ let g:loaded = 1
+ source
+ endif
+ END
+ " Can't have a NL in heredoc
+ let lines += ["silent! vim9 echo [0 \<NL> ? 'a' : 'b']"]
+ call writefile(lines, 'XsourceNul', '')
+ edit XsourceNul
+ source
+
+ bwipe!
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
--
2.27.0

View File

@ -1,634 +0,0 @@
From 96b9bf8f74af8abf1e30054f996708db7dc285be Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Sat, 24 Sep 2022 17:24:12 +0100
Subject: patch 9.0.0577: buffer underflow with unexpected :finally
Problem: Buffer underflow with unexpected :finally.
Solution: Check CSF_TRY can be found.
---
src/ex_eval.c | 523 +++++++++++++++++-----------------
src/testdir/test_trycatch.vim | 22 ++
2 files changed, 282 insertions(+), 263 deletions(-)
diff --git a/src/ex_eval.c b/src/ex_eval.c
index 5721b766e..77d6e8bb9 100644
--- a/src/ex_eval.c
+++ b/src/ex_eval.c
@@ -1935,128 +1935,127 @@ ex_finally(exarg_T *eap)
if (cmdmod_error(FALSE))
return;
- if (cstack->cs_trylevel <= 0 || cstack->cs_idx < 0)
+ for (idx = cstack->cs_idx; idx >= 0; --idx)
+ if (cstack->cs_flags[idx] & CSF_TRY)
+ break;
+ if (cstack->cs_trylevel <= 0 || idx < 0)
+ {
eap->errmsg = _(e_finally_without_try);
- else
+ return;
+ }
+
+ if (!(cstack->cs_flags[cstack->cs_idx] & CSF_TRY))
{
- if (!(cstack->cs_flags[cstack->cs_idx] & CSF_TRY))
- {
- eap->errmsg = get_end_emsg(cstack);
- for (idx = cstack->cs_idx - 1; idx > 0; --idx)
- if (cstack->cs_flags[idx] & CSF_TRY)
- break;
- // Make this error pending, so that the commands in the following
- // finally clause can be executed. This overrules also a pending
- // ":continue", ":break", ":return", or ":finish".
- pending = CSTP_ERROR;
- }
- else
- idx = cstack->cs_idx;
+ eap->errmsg = get_end_emsg(cstack);
+ // Make this error pending, so that the commands in the following
+ // finally clause can be executed. This overrules also a pending
+ // ":continue", ":break", ":return", or ":finish".
+ pending = CSTP_ERROR;
+ }
- if (cstack->cs_flags[idx] & CSF_FINALLY)
+ if (cstack->cs_flags[idx] & CSF_FINALLY)
+ {
+ // Give up for a multiple ":finally" and ignore it.
+ eap->errmsg = _(e_multiple_finally);
+ return;
+ }
+ rewind_conditionals(cstack, idx, CSF_WHILE | CSF_FOR,
+ &cstack->cs_looplevel);
+
+ /*
+ * Don't do something when the corresponding try block never got active
+ * (because of an inactive surrounding conditional or after an error or
+ * interrupt or throw) or for a ":finally" without ":try" or a multiple
+ * ":finally". After every other error (did_emsg or the conditional
+ * errors detected above) or after an interrupt (got_int) or an
+ * exception (did_throw), the finally clause must be executed.
+ */
+ skip = !(cstack->cs_flags[cstack->cs_idx] & CSF_TRUE);
+
+ if (!skip)
+ {
+ // When debugging or a breakpoint was encountered, display the
+ // debug prompt (if not already done). The user then knows that the
+ // finally clause is executed.
+ if (dbg_check_skipped(eap))
{
- // Give up for a multiple ":finally" and ignore it.
- eap->errmsg = _(e_multiple_finally);
- return;
+ // Handle a ">quit" debug command as if an interrupt had
+ // occurred before the ":finally". That is, discard the
+ // original exception and replace it by an interrupt
+ // exception.
+ (void)do_intthrow(cstack);
}
- rewind_conditionals(cstack, idx, CSF_WHILE | CSF_FOR,
- &cstack->cs_looplevel);
/*
- * Don't do something when the corresponding try block never got active
- * (because of an inactive surrounding conditional or after an error or
- * interrupt or throw) or for a ":finally" without ":try" or a multiple
- * ":finally". After every other error (did_emsg or the conditional
- * errors detected above) or after an interrupt (got_int) or an
- * exception (did_throw), the finally clause must be executed.
+ * If there is a preceding catch clause and it caught the exception,
+ * finish the exception now. This happens also after errors except
+ * when this is a multiple ":finally" or one not within a ":try".
+ * After an error or interrupt, this also discards a pending
+ * ":continue", ":break", ":finish", or ":return" from the preceding
+ * try block or catch clause.
*/
- skip = !(cstack->cs_flags[cstack->cs_idx] & CSF_TRUE);
+ cleanup_conditionals(cstack, CSF_TRY, FALSE);
- if (!skip)
+ if (cstack->cs_idx >= 0
+ && (cstack->cs_flags[cstack->cs_idx] & CSF_TRY))
{
- // When debugging or a breakpoint was encountered, display the
- // debug prompt (if not already done). The user then knows that the
- // finally clause is executed.
- if (dbg_check_skipped(eap))
- {
- // Handle a ">quit" debug command as if an interrupt had
- // occurred before the ":finally". That is, discard the
- // original exception and replace it by an interrupt
- // exception.
- (void)do_intthrow(cstack);
- }
-
- /*
- * If there is a preceding catch clause and it caught the exception,
- * finish the exception now. This happens also after errors except
- * when this is a multiple ":finally" or one not within a ":try".
- * After an error or interrupt, this also discards a pending
- * ":continue", ":break", ":finish", or ":return" from the preceding
- * try block or catch clause.
- */
- cleanup_conditionals(cstack, CSF_TRY, FALSE);
+ // Variables declared in the previous block can no longer be
+ // used.
+ leave_block(cstack);
+ enter_block(cstack);
+ }
- if (cstack->cs_idx >= 0
- && (cstack->cs_flags[cstack->cs_idx] & CSF_TRY))
+ /*
+ * Make did_emsg, got_int, did_throw pending. If set, they overrule
+ * a pending ":continue", ":break", ":return", or ":finish". Then
+ * we have particularly to discard a pending return value (as done
+ * by the call to cleanup_conditionals() above when did_emsg or
+ * got_int is set). The pending values are restored by the
+ * ":endtry", except if there is a new error, interrupt, exception,
+ * ":continue", ":break", ":return", or ":finish" in the following
+ * finally clause. A missing ":endwhile", ":endfor" or ":endif"
+ * detected here is treated as if did_emsg and did_throw had
+ * already been set, respectively in case that the error is not
+ * converted to an exception, did_throw had already been unset.
+ * We must not set did_emsg here since that would suppress the
+ * error message.
+ */
+ if (pending == CSTP_ERROR || did_emsg || got_int || did_throw)
+ {
+ if (cstack->cs_pending[cstack->cs_idx] == CSTP_RETURN)
{
- // Variables declared in the previous block can no longer be
- // used.
- leave_block(cstack);
- enter_block(cstack);
+ report_discard_pending(CSTP_RETURN,
+ cstack->cs_rettv[cstack->cs_idx]);
+ discard_pending_return(cstack->cs_rettv[cstack->cs_idx]);
}
-
- /*
- * Make did_emsg, got_int, did_throw pending. If set, they overrule
- * a pending ":continue", ":break", ":return", or ":finish". Then
- * we have particularly to discard a pending return value (as done
- * by the call to cleanup_conditionals() above when did_emsg or
- * got_int is set). The pending values are restored by the
- * ":endtry", except if there is a new error, interrupt, exception,
- * ":continue", ":break", ":return", or ":finish" in the following
- * finally clause. A missing ":endwhile", ":endfor" or ":endif"
- * detected here is treated as if did_emsg and did_throw had
- * already been set, respectively in case that the error is not
- * converted to an exception, did_throw had already been unset.
- * We must not set did_emsg here since that would suppress the
- * error message.
- */
- if (pending == CSTP_ERROR || did_emsg || got_int || did_throw)
- {
- if (cstack->cs_pending[cstack->cs_idx] == CSTP_RETURN)
- {
- report_discard_pending(CSTP_RETURN,
- cstack->cs_rettv[cstack->cs_idx]);
- discard_pending_return(cstack->cs_rettv[cstack->cs_idx]);
- }
- if (pending == CSTP_ERROR && !did_emsg)
- pending |= (THROW_ON_ERROR) ? CSTP_THROW : 0;
- else
- pending |= did_throw ? CSTP_THROW : 0;
- pending |= did_emsg ? CSTP_ERROR : 0;
- pending |= got_int ? CSTP_INTERRUPT : 0;
- cstack->cs_pending[cstack->cs_idx] = pending;
-
- // It's mandatory that the current exception is stored in the
- // cstack so that it can be rethrown at the ":endtry" or be
- // discarded if the finally clause is left by a ":continue",
- // ":break", ":return", ":finish", error, interrupt, or another
- // exception. When emsg() is called for a missing ":endif" or
- // a missing ":endwhile"/":endfor" detected here, the
- // exception will be discarded.
- if (did_throw && cstack->cs_exception[cstack->cs_idx]
- != current_exception)
- internal_error("ex_finally()");
- }
-
- /*
- * Set CSL_HAD_FINA, so do_cmdline() will reset did_emsg,
- * got_int, and did_throw and make the finally clause active.
- * This will happen after emsg() has been called for a missing
- * ":endif" or a missing ":endwhile"/":endfor" detected here, so
- * that the following finally clause will be executed even then.
- */
- cstack->cs_lflags |= CSL_HAD_FINA;
+ if (pending == CSTP_ERROR && !did_emsg)
+ pending |= (THROW_ON_ERROR) ? CSTP_THROW : 0;
+ else
+ pending |= did_throw ? CSTP_THROW : 0;
+ pending |= did_emsg ? CSTP_ERROR : 0;
+ pending |= got_int ? CSTP_INTERRUPT : 0;
+ cstack->cs_pending[cstack->cs_idx] = pending;
+
+ // It's mandatory that the current exception is stored in the
+ // cstack so that it can be rethrown at the ":endtry" or be
+ // discarded if the finally clause is left by a ":continue",
+ // ":break", ":return", ":finish", error, interrupt, or another
+ // exception. When emsg() is called for a missing ":endif" or
+ // a missing ":endwhile"/":endfor" detected here, the
+ // exception will be discarded.
+ if (did_throw && cstack->cs_exception[cstack->cs_idx]
+ != current_exception)
+ internal_error("ex_finally()");
}
+
+ /*
+ * Set CSL_HAD_FINA, so do_cmdline() will reset did_emsg,
+ * got_int, and did_throw and make the finally clause active.
+ * This will happen after emsg() has been called for a missing
+ * ":endif" or a missing ":endwhile"/":endfor" detected here, so
+ * that the following finally clause will be executed even then.
+ */
+ cstack->cs_lflags |= CSL_HAD_FINA;
}
}
@@ -2076,185 +2075,183 @@ ex_endtry(exarg_T *eap)
if (cmdmod_error(FALSE))
return;
- if (cstack->cs_trylevel <= 0 || cstack->cs_idx < 0)
- eap->errmsg = _(e_endtry_without_try);
- else
+ for (idx = cstack->cs_idx; idx >= 0; --idx)
+ if (cstack->cs_flags[idx] & CSF_TRY)
+ break;
+ if (cstack->cs_trylevel <= 0 || idx < 0)
{
- /*
- * Don't do something after an error, interrupt or throw in the try
- * block, catch clause, or finally clause preceding this ":endtry" or
- * when an error or interrupt occurred after a ":continue", ":break",
- * ":return", or ":finish" in a try block or catch clause preceding this
- * ":endtry" or when the try block never got active (because of an
- * inactive surrounding conditional or after an error or interrupt or
- * throw) or when there is a surrounding conditional and it has been
- * made inactive by a ":continue", ":break", ":return", or ":finish" in
- * the finally clause. The latter case need not be tested since then
- * anything pending has already been discarded. */
- skip = did_emsg || got_int || did_throw
+ eap->errmsg = _(e_endtry_without_try);
+ return;
+ }
+
+ /*
+ * Don't do something after an error, interrupt or throw in the try
+ * block, catch clause, or finally clause preceding this ":endtry" or
+ * when an error or interrupt occurred after a ":continue", ":break",
+ * ":return", or ":finish" in a try block or catch clause preceding this
+ * ":endtry" or when the try block never got active (because of an
+ * inactive surrounding conditional or after an error or interrupt or
+ * throw) or when there is a surrounding conditional and it has been
+ * made inactive by a ":continue", ":break", ":return", or ":finish" in
+ * the finally clause. The latter case need not be tested since then
+ * anything pending has already been discarded. */
+ skip = did_emsg || got_int || did_throw
|| !(cstack->cs_flags[cstack->cs_idx] & CSF_TRUE);
- if (!(cstack->cs_flags[cstack->cs_idx] & CSF_TRY))
- {
- eap->errmsg = get_end_emsg(cstack);
+ if (!(cstack->cs_flags[cstack->cs_idx] & CSF_TRY))
+ {
+ eap->errmsg = get_end_emsg(cstack);
- // Find the matching ":try" and report what's missing.
- idx = cstack->cs_idx;
- do
- --idx;
- while (idx > 0 && !(cstack->cs_flags[idx] & CSF_TRY));
- rewind_conditionals(cstack, idx, CSF_WHILE | CSF_FOR,
- &cstack->cs_looplevel);
- skip = TRUE;
+ // Find the matching ":try" and report what's missing.
+ rewind_conditionals(cstack, idx, CSF_WHILE | CSF_FOR,
+ &cstack->cs_looplevel);
+ skip = TRUE;
- /*
- * If an exception is being thrown, discard it to prevent it from
- * being rethrown at the end of this function. It would be
- * discarded by the error message, anyway. Resets did_throw.
- * This does not affect the script termination due to the error
- * since "trylevel" is decremented after emsg() has been called.
- */
- if (did_throw)
- discard_current_exception();
+ /*
+ * If an exception is being thrown, discard it to prevent it from
+ * being rethrown at the end of this function. It would be
+ * discarded by the error message, anyway. Resets did_throw.
+ * This does not affect the script termination due to the error
+ * since "trylevel" is decremented after emsg() has been called.
+ */
+ if (did_throw)
+ discard_current_exception();
- // report eap->errmsg, also when there already was an error
- did_emsg = FALSE;
- }
- else
- {
- idx = cstack->cs_idx;
+ // report eap->errmsg, also when there already was an error
+ did_emsg = FALSE;
+ }
+ else
+ {
+ idx = cstack->cs_idx;
- // Check the flags only when not in a skipped block.
- if (!skip && in_vim9script()
+ // Check the flags only when not in a skipped block.
+ if (!skip && in_vim9script()
&& (cstack->cs_flags[idx] & (CSF_CATCH|CSF_FINALLY)) == 0)
- {
- // try/endtry without any catch or finally: give an error and
- // continue.
- eap->errmsg = _(e_missing_catch_or_finally);
- }
-
- /*
- * If we stopped with the exception currently being thrown at this
- * try conditional since we didn't know that it doesn't have
- * a finally clause, we need to rethrow it after closing the try
- * conditional.
- */
- if (did_throw && (cstack->cs_flags[idx] & CSF_TRUE)
- && !(cstack->cs_flags[idx] & CSF_FINALLY))
- rethrow = TRUE;
- }
-
- // If there was no finally clause, show the user when debugging or
- // a breakpoint was encountered that the end of the try conditional has
- // been reached: display the debug prompt (if not already done). Do
- // this on normal control flow or when an exception was thrown, but not
- // on an interrupt or error not converted to an exception or when
- // a ":break", ":continue", ":return", or ":finish" is pending. These
- // actions are carried out immediately.
- if ((rethrow || (!skip
- && !(cstack->cs_flags[idx] & CSF_FINALLY)
- && !cstack->cs_pending[idx]))
- && dbg_check_skipped(eap))
{
- // Handle a ">quit" debug command as if an interrupt had occurred
- // before the ":endtry". That is, throw an interrupt exception and
- // set "skip" and "rethrow".
- if (got_int)
- {
- skip = TRUE;
- (void)do_intthrow(cstack);
- // The do_intthrow() call may have reset did_throw or
- // cstack->cs_pending[idx].
- rethrow = FALSE;
- if (did_throw && !(cstack->cs_flags[idx] & CSF_FINALLY))
- rethrow = TRUE;
- }
+ // try/endtry without any catch or finally: give an error and
+ // continue.
+ eap->errmsg = _(e_missing_catch_or_finally);
}
/*
- * If a ":return" is pending, we need to resume it after closing the
- * try conditional; remember the return value. If there was a finally
- * clause making an exception pending, we need to rethrow it. Make it
- * the exception currently being thrown.
+ * If we stopped with the exception currently being thrown at this
+ * try conditional since we didn't know that it doesn't have
+ * a finally clause, we need to rethrow it after closing the try
+ * conditional.
*/
- if (!skip)
+ if (did_throw && (cstack->cs_flags[idx] & CSF_TRUE)
+ && !(cstack->cs_flags[idx] & CSF_FINALLY))
+ rethrow = TRUE;
+ }
+
+ // If there was no finally clause, show the user when debugging or
+ // a breakpoint was encountered that the end of the try conditional has
+ // been reached: display the debug prompt (if not already done). Do
+ // this on normal control flow or when an exception was thrown, but not
+ // on an interrupt or error not converted to an exception or when
+ // a ":break", ":continue", ":return", or ":finish" is pending. These
+ // actions are carried out immediately.
+ if ((rethrow || (!skip && !(cstack->cs_flags[idx] & CSF_FINALLY)
+ && !cstack->cs_pending[idx]))
+ && dbg_check_skipped(eap))
+ {
+ // Handle a ">quit" debug command as if an interrupt had occurred
+ // before the ":endtry". That is, throw an interrupt exception and
+ // set "skip" and "rethrow".
+ if (got_int)
{
- pending = cstack->cs_pending[idx];
- cstack->cs_pending[idx] = CSTP_NONE;
- if (pending == CSTP_RETURN)
- rettv = cstack->cs_rettv[idx];
- else if (pending & CSTP_THROW)
- current_exception = cstack->cs_exception[idx];
+ skip = TRUE;
+ (void)do_intthrow(cstack);
+ // The do_intthrow() call may have reset did_throw or
+ // cstack->cs_pending[idx].
+ rethrow = FALSE;
+ if (did_throw && !(cstack->cs_flags[idx] & CSF_FINALLY))
+ rethrow = TRUE;
}
+ }
- /*
- * Discard anything pending on an error, interrupt, or throw in the
- * finally clause. If there was no ":finally", discard a pending
- * ":continue", ":break", ":return", or ":finish" if an error or
- * interrupt occurred afterwards, but before the ":endtry" was reached.
- * If an exception was caught by the last of the catch clauses and there
- * was no finally clause, finish the exception now. This happens also
- * after errors except when this ":endtry" is not within a ":try".
- * Restore "emsg_silent" if it has been reset by this try conditional.
- */
- (void)cleanup_conditionals(cstack, CSF_TRY | CSF_SILENT, TRUE);
+ /*
+ * If a ":return" is pending, we need to resume it after closing the
+ * try conditional; remember the return value. If there was a finally
+ * clause making an exception pending, we need to rethrow it. Make it
+ * the exception currently being thrown.
+ */
+ if (!skip)
+ {
+ pending = cstack->cs_pending[idx];
+ cstack->cs_pending[idx] = CSTP_NONE;
+ if (pending == CSTP_RETURN)
+ rettv = cstack->cs_rettv[idx];
+ else if (pending & CSTP_THROW)
+ current_exception = cstack->cs_exception[idx];
+ }
- if (cstack->cs_idx >= 0
- && (cstack->cs_flags[cstack->cs_idx] & CSF_TRY))
- leave_block(cstack);
- --cstack->cs_trylevel;
+ /*
+ * Discard anything pending on an error, interrupt, or throw in the
+ * finally clause. If there was no ":finally", discard a pending
+ * ":continue", ":break", ":return", or ":finish" if an error or
+ * interrupt occurred afterwards, but before the ":endtry" was reached.
+ * If an exception was caught by the last of the catch clauses and there
+ * was no finally clause, finish the exception now. This happens also
+ * after errors except when this ":endtry" is not within a ":try".
+ * Restore "emsg_silent" if it has been reset by this try conditional.
+ */
+ (void)cleanup_conditionals(cstack, CSF_TRY | CSF_SILENT, TRUE);
- if (!skip)
- {
- report_resume_pending(pending,
+ if (cstack->cs_idx >= 0 && (cstack->cs_flags[cstack->cs_idx] & CSF_TRY))
+ leave_block(cstack);
+ --cstack->cs_trylevel;
+
+ if (!skip)
+ {
+ report_resume_pending(pending,
(pending == CSTP_RETURN) ? rettv :
(pending & CSTP_THROW) ? (void *)current_exception : NULL);
- switch (pending)
- {
- case CSTP_NONE:
- break;
+ switch (pending)
+ {
+ case CSTP_NONE:
+ break;
- // Reactivate a pending ":continue", ":break", ":return",
- // ":finish" from the try block or a catch clause of this try
- // conditional. This is skipped, if there was an error in an
- // (unskipped) conditional command or an interrupt afterwards
- // or if the finally clause is present and executed a new error,
- // interrupt, throw, ":continue", ":break", ":return", or
- // ":finish".
- case CSTP_CONTINUE:
- ex_continue(eap);
- break;
- case CSTP_BREAK:
- ex_break(eap);
- break;
- case CSTP_RETURN:
- do_return(eap, FALSE, FALSE, rettv);
- break;
- case CSTP_FINISH:
- do_finish(eap, FALSE);
- break;
+ // Reactivate a pending ":continue", ":break", ":return",
+ // ":finish" from the try block or a catch clause of this try
+ // conditional. This is skipped, if there was an error in an
+ // (unskipped) conditional command or an interrupt afterwards
+ // or if the finally clause is present and executed a new error,
+ // interrupt, throw, ":continue", ":break", ":return", or
+ // ":finish".
+ case CSTP_CONTINUE:
+ ex_continue(eap);
+ break;
+ case CSTP_BREAK:
+ ex_break(eap);
+ break;
+ case CSTP_RETURN:
+ do_return(eap, FALSE, FALSE, rettv);
+ break;
+ case CSTP_FINISH:
+ do_finish(eap, FALSE);
+ break;
- // When the finally clause was entered due to an error,
- // interrupt or throw (as opposed to a ":continue", ":break",
- // ":return", or ":finish"), restore the pending values of
- // did_emsg, got_int, and did_throw. This is skipped, if there
- // was a new error, interrupt, throw, ":continue", ":break",
- // ":return", or ":finish". in the finally clause.
- default:
- if (pending & CSTP_ERROR)
- did_emsg = TRUE;
- if (pending & CSTP_INTERRUPT)
- got_int = TRUE;
- if (pending & CSTP_THROW)
- rethrow = TRUE;
- break;
- }
+ // When the finally clause was entered due to an error,
+ // interrupt or throw (as opposed to a ":continue", ":break",
+ // ":return", or ":finish"), restore the pending values of
+ // did_emsg, got_int, and did_throw. This is skipped, if there
+ // was a new error, interrupt, throw, ":continue", ":break",
+ // ":return", or ":finish". in the finally clause.
+ default:
+ if (pending & CSTP_ERROR)
+ did_emsg = TRUE;
+ if (pending & CSTP_INTERRUPT)
+ got_int = TRUE;
+ if (pending & CSTP_THROW)
+ rethrow = TRUE;
+ break;
}
-
- if (rethrow)
- // Rethrow the current exception (within this cstack).
- do_throw(cstack);
}
+
+ if (rethrow)
+ // Rethrow the current exception (within this cstack).
+ do_throw(cstack);
}
/*
diff --git a/src/testdir/test_trycatch.vim b/src/testdir/test_trycatch.vim
index aa42205a1..28cd39f04 100644
--- a/src/testdir/test_trycatch.vim
+++ b/src/testdir/test_trycatch.vim
@@ -3,6 +3,7 @@
source check.vim
source shared.vim
+import './vim9.vim' as v9
"-------------------------------------------------------------------------------
" Test environment {{{1
@@ -2008,6 +2009,27 @@ func Test_try_catch_errors()
call assert_fails('try | for i in range(5) | endif | endtry', 'E580:')
call assert_fails('try | while v:true | endtry', 'E170:')
call assert_fails('try | if v:true | endtry', 'E171:')
+
+ " this was using a negative index in cstack[]
+ let lines =<< trim END
+ try
+ for
+ if
+ endwhile
+ if
+ finally
+ END
+ call v9.CheckScriptFailure(lines, 'E690:')
+
+ let lines =<< trim END
+ try
+ for
+ if
+ endwhile
+ if
+ endtry
+ END
+ call v9.CheckScriptFailure(lines, 'E690:')
endfunc
" Test for verbose messages with :try :catch, and :finally {{{1
--
2.23.0

View File

@ -1,162 +0,0 @@
From 0ff01835a40f549c5c4a550502f62a2ac9ac447c Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Sat, 24 Sep 2022 19:20:30 +0100
Subject: [PATCH] patch 9.0.0579: using freed memory when 'tagfunc' wipes out
buffer
Problem: Using freed memory when 'tagfunc' wipes out buffer that holds
'complete'.
Solution: Make a copy of the option. Make sure cursor position is valid.
---
src/insexpand.c | 40 ++++++++++++++++++++++++-------
src/move.c | 1 +
src/testdir/test_ins_complete.vim | 20 ++++++++++++++--
3 files changed, 50 insertions(+), 11 deletions(-)
diff --git a/src/insexpand.c b/src/insexpand.c
index 24308e6..3585ef2 100644
--- a/src/insexpand.c
+++ b/src/insexpand.c
@@ -2485,7 +2485,8 @@ ins_compl_next_buf(buf_T *buf, int flag)
if (flag == 'w') // just windows
{
- if (buf == curbuf || wp == NULL) // first call for this flag/expansion
+ if (buf == curbuf || !win_valid(wp))
+ // first call for this flag/expansion or window was closed
wp = curwin;
while ((wp = (wp->w_next != NULL ? wp->w_next : firstwin)) != curwin
&& wp->w_buffer->b_scanned)
@@ -3188,9 +3189,10 @@ enum
*/
typedef struct
{
- char_u *e_cpt; // current entry in 'complete'
+ char_u *e_cpt_copy; // copy of 'complete'
+ char_u *e_cpt; // current entry in "e_cpt_copy"
buf_T *ins_buf; // buffer being scanned
- pos_T *cur_match_pos; // current match position
+ pos_T *cur_match_pos; // current match position
pos_T prev_match_pos; // previous match position
int set_match_pos; // save first_match_pos/last_match_pos
pos_T first_match_pos; // first match position
@@ -3257,7 +3259,8 @@ process_next_cpt_value(
st->set_match_pos = TRUE;
}
else if (vim_strchr((char_u *)"buwU", *st->e_cpt) != NULL
- && (st->ins_buf = ins_compl_next_buf(st->ins_buf, *st->e_cpt)) != curbuf)
+ && (st->ins_buf = ins_compl_next_buf(
+ st->ins_buf, *st->e_cpt)) != curbuf)
{
// Scan a buffer, but not the current one.
if (st->ins_buf->b_ml.ml_mfp != NULL) // loaded buffer
@@ -3756,19 +3759,30 @@ get_next_completion_match(int type, ins_compl_next_state_T *st, pos_T *ini)
static int
ins_compl_get_exp(pos_T *ini)
{
- static ins_compl_next_state_T st;
+ static ins_compl_next_state_T st;
+ static int st_cleared = FALSE;
int i;
int found_new_match;
int type = ctrl_x_mode;
if (!compl_started)
{
- FOR_ALL_BUFFERS(st.ins_buf)
- st.ins_buf->b_scanned = 0;
+ buf_T *buf;
+
+ FOR_ALL_BUFFERS(buf)
+ buf->b_scanned = 0;
+ if (!st_cleared)
+ {
+ CLEAR_FIELD(st);
+ st_cleared = TRUE;
+ }
st.found_all = FALSE;
st.ins_buf = curbuf;
- st.e_cpt = (compl_cont_status & CONT_LOCAL)
- ? (char_u *)"." : curbuf->b_p_cpt;
+ vim_free(st.e_cpt_copy);
+ // Make a copy of 'complete', if case the buffer is wiped out.
+ st.e_cpt_copy = vim_strsave((compl_cont_status & CONT_LOCAL)
+ ? (char_u *)"." : curbuf->b_p_cpt);
+ st.e_cpt = st.e_cpt_copy == NULL ? (char_u *)"" : st.e_cpt_copy;
st.last_match_pos = st.first_match_pos = *ini;
}
else if (st.ins_buf != curbuf && !buf_valid(st.ins_buf))
@@ -4112,6 +4126,7 @@ ins_compl_next(
int todo = count;
int advance;
int started = compl_started;
+ buf_T *orig_curbuf = curbuf;
// When user complete function return -1 for findstart which is next
// time of 'always', compl_shown_match become NULL.
@@ -4144,6 +4159,13 @@ ins_compl_next(
&num_matches) == -1)
return -1;
+ if (curbuf != orig_curbuf)
+ {
+ // In case some completion function switched buffer, don't want to
+ // insert the completion elsewhere.
+ return -1;
+ }
+
// Insert the text of the new completion, or the compl_leader.
if (compl_no_insert && !started)
{
diff --git a/src/move.c b/src/move.c
index b061a75..6c654ac 100644
--- a/src/move.c
+++ b/src/move.c
@@ -652,6 +652,7 @@ cursor_valid(void)
void
validate_cursor(void)
{
+ check_cursor();
check_cursor_moved(curwin);
if ((curwin->w_valid & (VALID_WCOL|VALID_WROW)) != (VALID_WCOL|VALID_WROW))
curs_columns(TRUE);
diff --git a/src/testdir/test_ins_complete.vim b/src/testdir/test_ins_complete.vim
index b303993..702a87c 100644
--- a/src/testdir/test_ins_complete.vim
+++ b/src/testdir/test_ins_complete.vim
@@ -628,9 +628,8 @@ func Test_pum_with_preview_win()
call writefile(lines, 'Xpreviewscript')
let buf = RunVimInTerminal('-S Xpreviewscript', #{rows: 12})
- call TermWait(buf, 50)
call term_sendkeys(buf, "Gi\<C-X>\<C-O>")
- call TermWait(buf, 100)
+ call TermWait(buf, 200)
call term_sendkeys(buf, "\<C-N>")
call VerifyScreenDump(buf, 'Test_pum_with_preview_win', {})
@@ -2233,4 +2232,21 @@ func Test_ins_complete_end_of_line()
bwipe!
endfunc
+func s:Tagfunc(t,f,o)
+ bwipe!
+ return []
+endfunc
+
+" This was using freed memory, since 'complete' was in a wiped out buffer.
+" Also using a window that was closed.
+func Test_tagfunc_wipes_out_buffer()
+ new
+ set complete=.,t,w,b,u,i
+ se tagfunc=s:Tagfunc
+ sil norm i
+
+ bwipe!
+endfunc
+
+
" vim: shiftwidth=2 sts=2 expandtab
--
2.27.0

View File

@ -1,70 +0,0 @@
From 8279af514ca7e5fd3c31cf13b0864163d1a0bfeb Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Mon, 26 Sep 2022 23:08:22 +0100
Subject: [PATCH] patch 9.0.0598: using negative array index with negative
width window
Problem: Using negative array index with negative width window.
Solution: Make sure the window width does not become negative.
---
src/testdir/test_cmdline.vim | 22 ++++++++++++++++++++++
src/window.c | 5 ++++-
2 files changed, 26 insertions(+), 1 deletion(-)
diff --git a/src/testdir/test_cmdline.vim b/src/testdir/test_cmdline.vim
index 440df96..ab3bfdf 100644
--- a/src/testdir/test_cmdline.vim
+++ b/src/testdir/test_cmdline.vim
@@ -3457,4 +3457,26 @@ func Test_cmdwin_freed_buffer_ptr()
bwipe!
endfunc
+" This was resulting in a window with negative width.
+" The test doesn't reproduce the illegal memory access though...
+func Test_cmdwin_split_often()
+ let lines = &lines
+ let columns = &columns
+ set t_WS=
+
+ try
+ set encoding=iso8859
+ set ruler
+ winsize 0 0
+ noremap 0 H
+ sil norm 0000000q:
+ catch /E36:/
+ endtry
+
+ bwipe!
+ set encoding=utf8
+ let &lines = lines
+ let &columns = columns
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/window.c b/src/window.c
index c91ebbc..73060db 100644
--- a/src/window.c
+++ b/src/window.c
@@ -2087,6 +2087,8 @@ win_equal_rec(
if (hnc) // add next_curwin size
{
next_curwin_size -= p_wiw - (m - n);
+ if (next_curwin_size < 0)
+ next_curwin_size = 0;
new_size += next_curwin_size;
room -= new_size - next_curwin_size;
}
@@ -6495,7 +6497,8 @@ scroll_to_fraction(win_T *wp, int prev_height)
void
win_new_width(win_T *wp, int width)
{
- wp->w_width = width;
+ // Should we give an error if width < 0?
+ wp->w_width = width < 0 ? 0 : width;
wp->w_lines_valid = 0;
changed_line_abv_curs_win(wp);
invalidate_botline_win(wp);
--
2.27.0

View File

@ -1,79 +0,0 @@
From ef976323e770315b5fca544efb6b2faa25674d15 Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Wed, 28 Sep 2022 11:48:30 +0100
Subject: [PATCH] patch 9.0.0614: SpellFileMissing autocmd may delete buffer
Problem: SpellFileMissing autocmd may delete buffer.
Solution: Disallow deleting the current buffer to avoid using freed memory.
---
src/buffer.c | 7 ++++++-
src/spell.c | 6 ++++++
src/testdir/test_autocmd.vim | 10 ++++++++++
3 files changed, 22 insertions(+), 1 deletion(-)
diff --git a/src/buffer.c b/src/buffer.c
index e775398..a85b2a8 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -461,7 +461,12 @@ can_unload_buffer(buf_T *buf)
}
}
if (!can_unload)
- semsg(_(e_attempt_to_delete_buffer_that_is_in_use_str), buf->b_fname);
+ {
+ char_u *fname = buf->b_fname != NULL ? buf->b_fname : buf->b_ffname;
+
+ semsg(_(e_attempt_to_delete_buffer_that_is_in_use_str),
+ fname != NULL ? fname : (char_u *)"[No Name]");
+ }
return can_unload;
}
diff --git a/src/spell.c b/src/spell.c
index 24abce4..3664425 100644
--- a/src/spell.c
+++ b/src/spell.c
@@ -1559,6 +1559,10 @@ spell_load_lang(char_u *lang)
sl.sl_slang = NULL;
sl.sl_nobreak = FALSE;
+ // Disallow deleting the current buffer. Autocommands can do weird things
+ // and cause "lang" to be freed.
+ ++curbuf->b_locked;
+
// We may retry when no spell file is found for the language, an
// autocommand may load it then.
for (round = 1; round <= 2; ++round)
@@ -1612,6 +1616,8 @@ spell_load_lang(char_u *lang)
STRCPY(fname_enc + STRLEN(fname_enc) - 3, "add.spl");
do_in_runtimepath(fname_enc, DIP_ALL, spell_load_cb, &sl);
}
+
+ --curbuf->b_locked;
}
/*
diff --git a/src/testdir/test_autocmd.vim b/src/testdir/test_autocmd.vim
index e9a59c2..bc74c29 100644
--- a/src/testdir/test_autocmd.vim
+++ b/src/testdir/test_autocmd.vim
@@ -2750,6 +2750,16 @@ func Test_FileType_spell()
setglobal spellfile=
endfunc
+" this was wiping out the current buffer and using freed memory
+func Test_SpellFileMissing_bwipe()
+ next 0
+ au SpellFileMissing 0 bwipe
+ call assert_fails('set spell spelllang=0', 'E937:')
+
+ au! SpellFileMissing
+ bwipe
+endfunc
+
" Test closing a window or editing another buffer from a FileChangedRO handler
" in a readonly buffer
func Test_FileChangedRO_winclose()
--
2.27.0

Binary file not shown.

View File

@ -1,52 +0,0 @@
From 36343ae0fb7247e060abfd35fb8e4337b33abb4b Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Sat, 15 Oct 2022 19:04:05 +0100
Subject: [PATCH] patch 9.0.0765: with a Visual block a put command column may
go negative
Problem: With a Visual block a put command column may go negative.
Solution: Check that the column does not become negative.
---
src/register.c | 2 ++
src/testdir/test_visual.vim | 12 ++++++++++++
2 files changed, 14 insertions(+)
diff --git a/src/register.c b/src/register.c
index 30e2001..41089a0 100644
--- a/src/register.c
+++ b/src/register.c
@@ -1945,6 +1945,8 @@ do_put(
// adjust '] mark
curbuf->b_op_end.lnum = curwin->w_cursor.lnum - 1;
curbuf->b_op_end.col = bd.textcol + totlen - 1;
+ if (curbuf->b_op_end.col < 0)
+ curbuf->b_op_end.col = 0;
curbuf->b_op_end.coladd = 0;
if (flags & PUT_CURSEND)
{
diff --git a/src/testdir/test_visual.vim b/src/testdir/test_visual.vim
index e965266..956a3d7 100644
--- a/src/testdir/test_visual.vim
+++ b/src/testdir/test_visual.vim
@@ -483,6 +483,18 @@ func Test_visual_block_put()
bw!
endfunc
+func Test_visual_block_put_invalid()
+ enew!
+ behave mswin
+ norm yy
+ norm v)Ps/^/
+ " this was causing the column to become negative
+ silent norm ggv)P
+
+ bwipe!
+ behave xterm
+endfunc
+
" Visual modes (v V CTRL-V) followed by an operator; count; repeating
func Test_visual_mode_op()
new
--
2.27.0

View File

@ -1,62 +0,0 @@
From 8f3c3c6cd044e3b5bf08dbfa3b3f04bb3f711bad Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Tue, 18 Oct 2022 17:05:54 +0100
Subject: [PATCH] patch 9.0.0789: dummy buffer ends up in a window
Problem: Dummy buffer ends up in a window.
Solution: Disallow navigating to a dummy buffer.
---
src/buffer.c | 7 +++++++
src/testdir/test_autocmd.vim | 20 ++++++++++++++++++++
2 files changed, 27 insertions(+)
diff --git a/src/buffer.c b/src/buffer.c
index 0849b7099..5a4825feb 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -1332,6 +1332,13 @@ do_buffer_ext(
)
return OK;
#endif
+ if ((action == DOBUF_GOTO || action == DOBUF_SPLIT)
+ && (buf->b_flags & BF_DUMMY))
+ {
+ // disallow navigating to the dummy buffer
+ semsg(_(e_buffer_nr_does_not_exist), count);
+ return FAIL;
+ }
#ifdef FEAT_GUI
need_mouse_correct = TRUE;
diff --git a/src/testdir/test_autocmd.vim b/src/testdir/test_autocmd.vim
index 0706e7307..6ba1b02df 100644
--- a/src/testdir/test_autocmd.vim
+++ b/src/testdir/test_autocmd.vim
@@ -3857,4 +3857,24 @@ func Test_autocmd_delete()
call assert_true(autocmd_delete([test_null_dict()]))
endfunc
+func Test_autocmd_split_dummy()
+ " Autocommand trying to split a window containing a dummy buffer.
+ auto BufReadPre * exe "sbuf " .. expand("<abuf>")
+ " Avoid the "W11" prompt
+ au FileChangedShell * let v:fcs_choice = 'reload'
+ func Xautocmd_changelist()
+ cal writefile(['Xtestfile2:4:4'], 'Xerr')
+ edit Xerr
+ lex 'Xtestfile2:4:4'
+ endfunc
+ call Xautocmd_changelist()
+ call assert_fails('call Xautocmd_changelist()', 'E86:')
+
+ au! BufReadPre
+ au! FileChangedShell
+ delfunc Xautocmd_changelist
+ bwipe! Xerr
+ call delete('Xerr')
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
--
2.27.0

View File

@ -1,72 +0,0 @@
From d0fab10ed2a86698937e3c3fed2f10bd9bb5e731 Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Thu, 20 Oct 2022 16:03:33 +0100
Subject: [PATCH] patch 9.0.0805: filetype autocmd may cause freed memory
access
Problem: Filetype autocmd may cause freed memory access.
Solution: Set the quickfix-busy flag while filling the buffer.
---
src/quickfix.c | 6 ++++++
src/testdir/test_quickfix.vim | 16 ++++++++++++++++
2 files changed, 22 insertions(+)
diff --git a/src/quickfix.c b/src/quickfix.c
index a90611475ab1..f85fff56f23d 100644
--- a/src/quickfix.c
+++ b/src/quickfix.c
@@ -4543,6 +4543,9 @@ qf_update_buffer(qf_info_T *qi, qfline_T *old_last)
qf_winid = win->w_id;
}
+ // autocommands may cause trouble
+ incr_quickfix_busy();
+
if (old_last == NULL)
// set curwin/curbuf to buf and save a few things
aucmd_prepbuf(&aco, buf);
@@ -4564,6 +4567,9 @@ qf_update_buffer(qf_info_T *qi, qfline_T *old_last)
// when the added lines are not visible.
if ((win = qf_find_win(qi)) != NULL && old_line_count < win->w_botline)
redraw_buf_later(buf, NOT_VALID);
+
+ // always called after incr_quickfix_busy()
+ decr_quickfix_busy();
}
}
diff --git a/src/testdir/test_quickfix.vim b/src/testdir/test_quickfix.vim
index 2ee754b39690..bcaef5da175c 100644
--- a/src/testdir/test_quickfix.vim
+++ b/src/testdir/test_quickfix.vim
@@ -3471,6 +3471,21 @@ func Test_resize_from_copen()
endtry
endfunc
+func Test_filetype_autocmd()
+ " this changes the location list while it is in use to fill a buffer
+ lexpr ''
+ lopen
+ augroup FT_loclist
+ au FileType * call setloclist(0, [], 'f')
+ augroup END
+ silent! lolder
+ lexpr ''
+
+ augroup FT_loclist
+ au! FileType
+ augroup END
+endfunc
+
func Test_vimgrep_with_textlock()
new
@@ -6380,4 +6395,5 @@ func Test_loclist_replace_autocmd()
call setloclist(0, [], 'f')
endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
--
2.33.0

View File

@ -1,145 +0,0 @@
From cc762a48d42b579fb7bdec2c614636b830342dd5 Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Fri, 25 Nov 2022 13:03:31 +0000
Subject: [PATCH] patch 9.0.0947: invalid memory access in substitute with
function
Problem: Invalid memory access in substitute with function that goes to
another file.
Solution: Check for text locked in CTRL-W gf.
---
src/normal.c | 33 ++++++++++++++++++++++++---------
src/proto/normal.pro | 1 +
src/testdir/test_substitute.vim | 19 +++++++++++++++++++
src/window.c | 4 +++-
4 files changed, 47 insertions(+), 10 deletions(-)
diff --git a/src/normal.c b/src/normal.c
index 938ae718efa2..0d1eba759e69 100644
--- a/src/normal.c
+++ b/src/normal.c
@@ -192,13 +192,33 @@ check_text_locked(oparg_T *oap)
{
if (text_locked())
{
- clearopbeep(oap);
+ if (oap != NULL)
+ clearopbeep(oap);
text_locked_msg();
return TRUE;
}
return FALSE;
}
+/*
+ * If text is locked, "curbuf_lock" or "allbuf_lock" is set:
+ * Give an error message, possibly beep and return TRUE.
+ * "oap" may be NULL.
+ */
+ int
+check_text_or_curbuf_locked(oparg_T *oap)
+{
+ if (check_text_locked(oap))
+ return TRUE;
+ if (curbuf_locked())
+ {
+ if (oap != NULL)
+ clearop(oap);
+ return TRUE;
+ }
+ return FALSE;
+}
+
/*
* Handle the count before a normal command and set cap->count0.
*/
@@ -816,8 +836,7 @@ normal_cmd(
goto normal_end;
}
- if ((nv_cmds[idx].cmd_flags & NV_NCW)
- && (check_text_locked(oap) || curbuf_locked()))
+ if ((nv_cmds[idx].cmd_flags & NV_NCW) && check_text_or_curbuf_locked(oap))
// this command is not allowed now
goto normal_end;
@@ -4058,13 +4077,9 @@ nv_gotofile(cmdarg_T *cap)
char_u *ptr;
linenr_T lnum = -1;
- if (check_text_locked(cap->oap))
- return;
- if (curbuf_locked())
- {
- clearop(cap->oap);
+ if (check_text_or_curbuf_locked(cap->oap))
return;
- }
+
#ifdef FEAT_PROP_POPUP
if (ERROR_IF_TERM_POPUP_WINDOW)
return;
diff --git a/src/proto/normal.pro b/src/proto/normal.pro
index 106d0e1..eff08df 100644
--- a/src/proto/normal.pro
+++ b/src/proto/normal.pro
@@ -1,4 +1,5 @@
/* normal.c */
+int check_text_or_curbuf_locked(oparg_T *oap);
void normal_cmd(oparg_T *oap, int toplevel);
void check_visual_highlight(void);
void end_visual_mode(void);
diff --git a/src/testdir/test_substitute.vim b/src/testdir/test_substitute.vim
index 7e7ccff..73c8c57 100644
--- a/src/testdir/test_substitute.vim
+++ b/src/testdir/test_substitute.vim
@@ -1076,6 +1076,25 @@ func Test_sub_edit_scriptfile()
bwipe!
endfunc
+" This was editing another file from the expression.
+func Test_sub_expr_goto_other_file()
+ call writefile([''], 'Xfileone', 'D')
+ enew!
+ call setline(1, ['a', 'b', 'c', 'd',
+ \ 'Xfileone zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz'])
+
+ func g:SplitGotoFile()
+ exe "sil! norm 0\<C-W>gf"
+ return ''
+ endfunc
+
+ $
+ s/\%')/\=g:SplitGotoFile()
+
+ delfunc g:SplitGotoFile
+ bwipe!
+endfunc
+
" Test for the 2-letter and 3-letter :substitute commands
func Test_substitute_short_cmd()
new
diff --git a/src/window.c b/src/window.c
index 97cc77035f95..a2bebcaea4df 100644
--- a/src/window.c
+++ b/src/window.c
@@ -534,6 +534,8 @@ do_window(
case Ctrl_F:
wingotofile:
CHECK_CMDWIN;
+ if (check_text_or_curbuf_locked(NULL))
+ break;
ptr = grab_file_name(Prenum1, &lnum);
if (ptr != NULL)
@@ -857,7 +859,7 @@ win_split(int size, int flags)
* When "new_wp" is NULL: split the current window in two.
* When "new_wp" is not NULL: insert this window at the far
* top/left/right/bottom.
- * return FAIL for failure, OK otherwise
+ * Return FAIL for failure, OK otherwise.
*/
int
win_split_ins(
--
2.33.0

View File

@ -1,55 +0,0 @@
From c3d27ada14acd02db357f2d16347acc22cb17e93 Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Mon, 14 Nov 2022 20:52:14 +0000
Subject: [PATCH] patch 9.0.0882: using freed memory after SpellFileMissing
autocmd uses bwipe
Problem: Using freed memory after SpellFileMissing autocmd uses bwipe.
Solution: Bail out if the window no longer exists.
---
src/spell.c | 4 ++--
src/testdir/test_spell.vim | 13 +++++++++++++
2 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/src/spell.c b/src/spell.c
index 3664425..d204a95 100644
--- a/src/spell.c
+++ b/src/spell.c
@@ -2101,8 +2101,8 @@ did_set_spelllang(win_T *wp)
{
spell_load_lang(lang);
// SpellFileMissing autocommands may do anything, including
- // destroying the buffer we are using...
- if (!bufref_valid(&bufref))
+ // destroying the buffer we are using or closing the window.
+ if (!bufref_valid(&bufref) || !win_valid_any_tab(wp))
{
ret_msg = N_(e_spellfilemising_autocommand_deleted_buffer);
goto theend;
diff --git a/src/testdir/test_spell.vim b/src/testdir/test_spell.vim
index bc948b0..33f0931 100644
--- a/src/testdir/test_spell.vim
+++ b/src/testdir/test_spell.vim
@@ -157,6 +157,19 @@ func Test_spell_file_missing()
%bwipe!
endfunc
+func Test_spell_file_missing_bwipe()
+ " this was using a window that was wiped out in a SpellFileMissing autocmd
+ set spelllang=xy
+ au SpellFileMissing * n0
+ set spell
+ au SpellFileMissing * bw
+ snext somefile
+
+ au! SpellFileMissing
+ bwipe!
+ set nospell spelllang=en
+endfunc
+
func Test_spelldump()
" In case the spell file is not found avoid getting the download dialog, we
" would get stuck at the prompt.
--
2.33.0

View File

@ -1,55 +0,0 @@
From cdef1cefa2a440911c727558562f83ed9b00e16b Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Thu, 20 Oct 2022 14:17:18 +0100
Subject: [PATCH] patch 9.0.0804: crash when trying to divide a number by -1
Problem: Crash when trying to divice the largest negative number by -1.
Solution: Handle this case specifically.
---
src/eval.c | 8 +++++++-
src/testdir/test_expr.vim | 6 ++++++
2 files changed, 13 insertions(+), 1 deletion(-)
diff --git a/src/eval.c b/src/eval.c
index 1652fcb4ae48..062fab0ac949 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -82,6 +82,12 @@ num_divide(varnumber_T n1, varnumber_T n2, int *failed)
else
result = VARNUM_MAX;
}
+ else if (n1 == VARNUM_MIN && n2 == -1)
+ {
+ // specific case: trying to do VARNUM_MIN / -1 results in a positive
+ // number that doesn't fit in varnumber_T and causes an FPE
+ result = VARNUM_MAX;
+ }
else
result = n1 / n2;
@@ -5906,7 +5912,7 @@ var2fpos(
}
/*
- * Convert list in "arg" into position "psop" and optional file number "fnump".
+ * Convert list in "arg" into position "posp" and optional file number "fnump".
* When "fnump" is NULL there is no file number, only 3 items: [lnum, col, off]
* Note that the column is passed on as-is, the caller may want to decrement
* it to use 1 for the first column.
diff --git a/src/testdir/test_expr.vim b/src/testdir/test_expr.vim
index b47896340f60..e1fed369b747 100644
--- a/src/testdir/test_expr.vim
+++ b/src/testdir/test_expr.vim
@@ -764,6 +764,12 @@ func Test_eval_after_if()
call assert_equal('b', s:val)
endfunc
+func Test_divide_by_zero()
+ " only tests that this doesn't crash, the result is not important
+ echo 0 / 0
+ echo 0 / 0 / -1
+endfunc
+
" Test for command-line completion of expressions
func Test_expr_completion()
CheckFeature cmdline_compl

View File

@ -1,34 +0,0 @@
From a63ad78ed31e36dbdf3a9cd28071dcdbefce7d19 Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Wed, 31 Aug 2022 12:01:54 +0100
Subject: [PATCH] patch 9.0.0339: no check if the return value of XChangeGC()
is NULL
Problem: No check if the return value of XChangeGC() is NULL.
Solution: Only use the return value when it is not NULL. (closes #11020)
---
src/gui_x11.c | 10 +++++++---
1 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/src/gui_x11.c b/src/gui_x11.c
index 6e3e903be462..7293ac4900a6 100644
--- a/src/gui_x11.c
+++ b/src/gui_x11.c
@@ -2231,10 +2231,14 @@ gui_x11_create_blank_mouse(void)
{
Pixmap blank_pixmap = XCreatePixmap(gui.dpy, gui.wid, 1, 1, 1);
GC gc = XCreateGC(gui.dpy, blank_pixmap, (unsigned long)0, (XGCValues*)0);
- XDrawPoint(gui.dpy, blank_pixmap, gc, 0, 0);
- XFreeGC(gui.dpy, gc);
+
+ if (gc != NULL)
+ {
+ XDrawPoint(gui.dpy, blank_pixmap, gc, 0, 0);
+ XFreeGC(gui.dpy, gc);
+ }
return XCreatePixmapCursor(gui.dpy, blank_pixmap, blank_pixmap,
- (XColor*)&gui.norm_pixel, (XColor*)&gui.norm_pixel, 0, 0);
+ (XColor*)&gui.norm_pixel, (XColor*)&gui.norm_pixel, 0, 0);
}
/*

View File

@ -1,44 +0,0 @@
From 7b17eb4b063a234376c1ec909ee293e42cff290c Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Wed, 4 Jan 2023 14:31:49 +0000
Subject: [PATCH] patch 9.0.1143: invalid memory access with bad 'statusline'
value
Problem: Invalid memory access with bad 'statusline' value.
Solution: Avoid going over the NUL at the end.
---
src/buffer.c | 2 ++
src/testdir/test_statusline.vim | 7 +++++++
2 files changed, 9 insertions(+)
diff --git a/src/buffer.c b/src/buffer.c
index 98568987894e..40168226160c 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -4576,6 +4576,8 @@ build_stl_str_hl(
#endif
if (vim_strchr(STL_ALL, *s) == NULL)
{
+ if (*s == NUL) // can happen with "%0"
+ break;
s++;
continue;
}
diff --git a/src/testdir/test_statusline.vim b/src/testdir/test_statusline.vim
index a829597655bf..23613bfed37b 100644
--- a/src/testdir/test_statusline.vim
+++ b/src/testdir/test_statusline.vim
@@ -436,6 +436,13 @@ func Test_statusline()
set splitbelow&
endfunc
+func Test_statusline_trailing_percent_zero()
+ " this was causing illegal memory access
+ set laststatus=2 stl=%!%0
+ call assert_fails('redraw', 'E15: Invalid expression: "%0"')
+ set laststatus& stl&
+endfunc
+
func Test_statusline_visual()
func CallWordcount()
call wordcount()

View File

@ -1,98 +0,0 @@
From c32949b0779106ed5710ae3bffc5053e49083ab4 Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Wed, 4 Jan 2023 15:56:51 +0000
Subject: [PATCH] patch 9.0.1144: reading beyond text
Problem: Reading beyond text.
Solution: Add strlen_maxlen() and use it.
---
src/message.c | 3 ++-
src/proto/strings.pro | 1 +
src/strings.c | 15 ++++++++++++++-
src/testdir/test_cmdline.vim | 11 +++++++++++
4 files changed, 28 insertions(+), 2 deletions(-)
diff --git a/src/message.c b/src/message.c
index becb280..c53c44f 100644
--- a/src/message.c
+++ b/src/message.c
@@ -2806,7 +2806,8 @@ msg_puts_printf(char_u *str, int maxlen)
{
char_u *tofree = NULL;
- if (maxlen > 0 && STRLEN(p) > (size_t)maxlen)
+ if (maxlen > 0 && vim_strlen_maxlen((char *)p, (size_t)maxlen)
+ >= (size_t)maxlen)
{
tofree = vim_strnsave(p, (size_t)maxlen);
p = tofree;
diff --git a/src/proto/strings.pro b/src/proto/strings.pro
index 778ec90..1bd4dcb 100644
--- a/src/proto/strings.pro
+++ b/src/proto/strings.pro
@@ -12,6 +12,7 @@ char_u *strlow_save(char_u *orig);
void del_trailing_spaces(char_u *ptr);
void vim_strncpy(char_u *to, char_u *from, size_t len);
void vim_strcat(char_u *to, char_u *from, size_t tosize);
+size_t vim_strlen_maxlen(char *s, size_t maxlen);
int vim_stricmp(char *s1, char *s2);
int vim_strnicmp(char *s1, char *s2, size_t len);
char_u *vim_strchr(char_u *string, int c);
diff --git a/src/strings.c b/src/strings.c
index 0313e74..df06c3f 100644
--- a/src/strings.c
+++ b/src/strings.c
@@ -525,6 +525,19 @@ vim_strcat(char_u *to, char_u *from, size_t tosize)
mch_memmove(to + tolen, from, fromlen + 1);
}
+/*
+ * A version of strlen() that has a maximum length.
+ */
+ size_t
+vim_strlen_maxlen(char *s, size_t maxlen)
+{
+ size_t i;
+ for (i = 0; i < maxlen; ++i)
+ if (s[i] == NUL)
+ break;
+ return i;
+}
+
#if (!defined(HAVE_STRCASECMP) && !defined(HAVE_STRICMP)) || defined(PROTO)
/*
* Compare two strings, ignoring case, using current locale.
@@ -582,7 +595,7 @@ vim_strnicmp(char *s1, char *s2, size_t len)
* 128 to 255 correctly. It also doesn't return a pointer to the NUL at the
* end of the string.
*/
- char_u *
+ char_u *
vim_strchr(char_u *string, int c)
{
char_u *p;
diff --git a/src/testdir/test_cmdline.vim b/src/testdir/test_cmdline.vim
index ab3bfdf..083f63e 100644
--- a/src/testdir/test_cmdline.vim
+++ b/src/testdir/test_cmdline.vim
@@ -574,6 +574,17 @@ func Test_getcompletion()
call assert_fails('call getcompletion("abc", [])', 'E475:')
endfunc
+func Test_multibyte_expression()
+ " This was using uninitialized memory.
+ let lines =<< trim END
+ set verbose=6
+ norm @=ٷ
+ qall!
+ END
+ call writefile(lines, 'XmultiScript', 'D')
+ call RunVim('', '', '-u NONE -n -e -s -S XmultiScript')
+endfunc
+
" Test for getcompletion() with "fuzzy" in 'wildoptions'
func Test_getcompletion_wildoptions()
let save_wildoptions = &wildoptions
--
2.33.0

View File

@ -1,59 +0,0 @@
From 3ac1d97a1d9353490493d30088256360435f7731 Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Wed, 4 Jan 2023 17:17:54 +0000
Subject: [PATCH] patch 9.0.1145: invalid memory access with recursive
substitute expression
Problem: Invalid memory access with recursive substitute expression.
Solution: Check the return value of vim_regsub().
---
src/eval.c | 5 +++++
src/testdir/test_substitute.vim | 16 ++++++++++++++++
2 files changed, 21 insertions(+)
diff --git a/src/eval.c b/src/eval.c
index 2fbd867ab..9ca805061 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -6969,6 +6969,11 @@ do_string_sub(
* - The text after the match.
*/
sublen = vim_regsub(&regmatch, sub, expr, tail, 0, REGSUB_MAGIC);
+ if (sublen <= 0)
+ {
+ ga_clear(&ga);
+ break;
+ }
if (ga_grow(&ga, (int)((end - tail) + sublen -
(regmatch.endp[0] - regmatch.startp[0]))) == FAIL)
{
diff --git a/src/testdir/test_substitute.vim b/src/testdir/test_substitute.vim
index 251322337..4268aab03 100644
--- a/src/testdir/test_substitute.vim
+++ b/src/testdir/test_substitute.vim
@@ -1095,6 +1095,22 @@ func Test_sub_expr_goto_other_file()
bwipe!
endfunc
+func Test_recursive_expr_substitute()
+ " this was reading invalid memory
+ let lines =<< trim END
+ func Repl(g, n)
+ s
+ r%:s000
+ endfunc
+ next 0
+ let caught = 0
+ s/\%')/\=Repl(0, 0)
+ qall!
+ END
+ call writefile(lines, 'XexprSubst', 'D')
+ call RunVim([], [], '--clean -S XexprSubst')
+endfunc
+
" Test for the 2-letter and 3-letter :substitute commands
func Test_substitute_short_cmd()
new
--
2.27.0

View File

@ -1,44 +0,0 @@
From 232bdaaca98c34a99ffadf27bf6ee08be6cc8f6a Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Fri, 13 Jan 2023 14:17:58 +0000
Subject: [PATCH] patch 9.0.1189: invalid memory access with folding and using
"L"
Problem: Invalid memory access with folding and using "L".
Solution: Prevent the cursor from moving to line zero.
---
src/normal.c | 3 ++-
src/testdir/test_fold.vim | 8 ++++++++
2 files changed, 10 insertions(+), 1 deletion(-)
diff --git a/src/normal.c b/src/normal.c
index c319be599ad7..3d9f74dec558 100644
--- a/src/normal.c
+++ b/src/normal.c
@@ -3757,7 +3757,8 @@ nv_scroll(cmdarg_T *cap)
{
(void)hasFolding(curwin->w_cursor.lnum,
&curwin->w_cursor.lnum, NULL);
- --curwin->w_cursor.lnum;
+ if (curwin->w_cursor.lnum > curwin->w_topline)
+ --curwin->w_cursor.lnum;
}
}
else
diff --git a/src/testdir/test_fold.vim b/src/testdir/test_fold.vim
index adf9e5207838..f915a661336b 100644
--- a/src/testdir/test_fold.vim
+++ b/src/testdir/test_fold.vim
@@ -1547,4 +1547,12 @@ func Test_sort_closed_fold()
bw!
endfunc
+func Test_indent_with_L_command()
+ " The "L" command moved the cursor to line zero, causing the text saved for
+ " undo to use line number -1, which caused trouble for undo later.
+ new
+ sil! norm 8R V{zf8=Lu
+ bwipe!
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab

View File

@ -1,40 +0,0 @@
From 11977f917506d950b7e0cae558bd9189260b253b Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Sat, 21 Jan 2023 13:09:19 +0000
Subject: [PATCH] patch 9.0.1225: reading past the end of a line when
formatting text
Problem: Reading past the end of a line when formatting text.
Solution: Check for not going over the end of the line.
---
src/textformat.c | 10 +++++++++-
1 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/src/textformat.c b/src/textformat.c
index 6a93890bd2c4..7ebbc8849a45 100644
--- a/src/textformat.c
+++ b/src/textformat.c
@@ -540,6 +540,9 @@ same_leader(
if (leader1_len == 0)
return (leader2_len == 0);
+ char_u *lnum_line = NULL;
+ int line_len = 0;
+
// If first leader has 'f' flag, the lines can be joined only if the
// second line does not have a leader.
// If first leader has 'e' flag, the lines can never be joined.
@@ -555,7 +558,12 @@ same_leader(
return FALSE;
if (*p == COM_START)
{
- if (*(ml_get(lnum) + leader1_len) == NUL)
+ if (lnum_line == NULL)
+ {
+ lnum_line = ml_get(lnum);
+ line_len = (int)STRLEN(lnum_line);
+ }
+ if (line_len <= leader1_len)
return FALSE;
if (leader2_flags == NULL || leader2_len == 0)
return FALSE;

View File

@ -1,63 +0,0 @@
From 1c73b65229c25e3c1fd8824ba958f7cc4d604f9c Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Fri, 3 Mar 2023 21:11:52 +0000
Subject: [PATCH] patch 9.0.1376: accessing invalid memory with put in Visual
block mode
Problem: Accessing invalid memory with put in Visual block mode.
Solution: Adjust the cursor column if needed.
---
src/register.c | 11 ++++++++++-
src/testdir/test_put.vim | 11 +++++++++++
2 files changed, 21 insertions(+), 1 deletion(-)
diff --git a/src/register.c b/src/register.c
index 4dc0a68fd7a4..461363be378d 100644
--- a/src/register.c
+++ b/src/register.c
@@ -1913,7 +1913,7 @@ do_put(
ptr += yanklen;
// insert block's trailing spaces only if there's text behind
- if ((j < count - 1 || !shortline) && spaces)
+ if ((j < count - 1 || !shortline) && spaces > 0)
{
vim_memset(ptr, ' ', (size_t)spaces);
ptr += spaces;
@@ -2274,6 +2274,15 @@ do_put(
msgmore(nr_lines);
curwin->w_set_curswant = TRUE;
+ // Make sure the cursor is not after the NUL.
+ int len = (int)STRLEN(ml_get_curline());
+ if (curwin->w_cursor.col > len)
+ {
+ if (cur_ve_flags == VE_ALL)
+ curwin->w_cursor.coladd = curwin->w_cursor.col - len;
+ curwin->w_cursor.col = len;
+ }
+
end:
if (cmdmod.cmod_flags & CMOD_LOCKMARKS)
{
diff --git a/src/testdir/test_put.vim b/src/testdir/test_put.vim
index 66438bd3f69c..a6cea74efb6c 100644
--- a/src/testdir/test_put.vim
+++ b/src/testdir/test_put.vim
@@ -231,5 +231,16 @@ func Test_put_visual_mode()
set selection&
endfunc
+func Test_put_visual_block_mode()
+ enew
+ exe "norm 0R\<CR>\<C-C>V"
+ sil exe "norm \<C-V>c \<MiddleDrag>"
+ set ve=all
+ sil norm vz=p
+
+ bwipe!
+ set ve=
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab

View File

@ -1,47 +0,0 @@
From c99cbf8f289bdda5d4a77d7ec415850a520330ba Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Sat, 4 Mar 2023 14:13:10 +0000
Subject: [PATCH] patch 9.0.1378: illegal memory access when using virtual
editing
Problem: Illegal memory access when using virtual editing.
Solution: Make sure "startspaces" is not negative.
---
src/register.c | 2 ++
src/testdir/test_virtualedit.vim | 10 ++++++++++
2 files changed, 12 insertions(+)
diff --git a/src/register.c b/src/register.c
index 461363be378d..f3df79cfd642 100644
--- a/src/register.c
+++ b/src/register.c
@@ -1247,6 +1247,8 @@ op_yank(oparg_T *oap, int deleting, int mess)
// double-count it.
bd.startspaces = (ce - cs + 1)
- oap->start.coladd;
+ if (bd.startspaces < 0)
+ bd.startspaces = 0;
startcol++;
}
}
diff --git a/src/testdir/test_virtualedit.vim b/src/testdir/test_virtualedit.vim
index 71cea427bac1..edaae678609d 100644
--- a/src/testdir/test_virtualedit.vim
+++ b/src/testdir/test_virtualedit.vim
@@ -88,6 +88,16 @@ func Test_edit_change()
set virtualedit=
endfunc
+func Test_edit_special_char()
+ new
+ se ve=all
+ norm a0
+ sil! exe "norm o00000\<Nul>k<a0s"
+
+ bwipe!
+ set virtualedit=
+endfunc
+
" Tests for pasting at the beginning, end and middle of a tab character
" in virtual edit mode.
func Test_paste_in_tab()

View File

@ -1,137 +0,0 @@
From 7ac5023a5f1a37baafbe1043645f97ba3443d9f6 Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Tue, 7 Mar 2023 21:05:04 +0000
Subject: [PATCH] patch 9.0.1392: using NULL pointer with nested :open command
Problem: Using NULL pointer with nested :open command.
Solution: Check that ccline.cmdbuff is not NULL.
---
src/getchar.c | 17 ++++++++++-------
src/testdir/term_util.vim | 5 +++++
src/testdir/test_ex_mode.vim | 22 ++++++++++++++++++++++
3 files changed, 37 insertions(+), 7 deletions(-)
diff --git a/src/getchar.c b/src/getchar.c
index 6645be8a0ebd..dac57eb26c61 100644
--- a/src/getchar.c
+++ b/src/getchar.c
@@ -3019,7 +3019,7 @@ check_end_reg_executing(int advance)
static int
vgetorpeek(int advance)
{
- int c, c1;
+ int c;
int timedout = FALSE; // waited for more than 1 second
// for mapping to complete
int mapdepth = 0; // check for recursive mapping
@@ -3386,7 +3386,7 @@ vgetorpeek(int advance)
#ifdef FEAT_CMDL_INFO
showcmd_idx = 0;
#endif
- c1 = 0;
+ int showing_partial = FALSE;
if (typebuf.tb_len > 0 && advance && !exmode_active)
{
if (((State & (MODE_NORMAL | MODE_INSERT))
@@ -3401,7 +3401,7 @@ vgetorpeek(int advance)
edit_putchar(typebuf.tb_buf[typebuf.tb_off
+ typebuf.tb_len - 1], FALSE);
setcursor(); // put cursor back where it belongs
- c1 = 1;
+ showing_partial = TRUE;
}
#ifdef FEAT_CMDL_INFO
// need to use the col and row from above here
@@ -3420,8 +3420,10 @@ vgetorpeek(int advance)
#endif
}
- // this looks nice when typing a dead character map
+ // This looks nice when typing a dead character map.
+ // There is no actual command line for get_number().
if ((State & MODE_CMDLINE)
+ && get_cmdline_info()->cmdbuff != NULL
#if defined(FEAT_CRYPT) || defined(FEAT_EVAL)
&& cmdline_star == 0
#endif
@@ -3430,7 +3432,7 @@ vgetorpeek(int advance)
{
putcmdline(typebuf.tb_buf[typebuf.tb_off
+ typebuf.tb_len - 1], FALSE);
- c1 = 1;
+ showing_partial = TRUE;
}
}
@@ -3466,11 +3468,12 @@ vgetorpeek(int advance)
if (showcmd_idx != 0)
pop_showcmd();
#endif
- if (c1 == 1)
+ if (showing_partial)
{
if (State & MODE_INSERT)
edit_unputchar();
- if (State & MODE_CMDLINE)
+ if ((State & MODE_CMDLINE)
+ && get_cmdline_info()->cmdbuff != NULL)
unputcmdline();
else
setcursor(); // put cursor back where it belongs
diff --git a/src/testdir/term_util.vim b/src/testdir/term_util.vim
index 0f0373184505..88e2b33d083b 100644
--- a/src/testdir/term_util.vim
+++ b/src/testdir/term_util.vim
@@ -55,6 +55,7 @@ endfunc
" "cols" - width of the terminal window (max. 78)
" "statusoff" - number of lines the status is offset from default
" "wait_for_ruler" - if zero then don't wait for ruler to show
+" "no_clean" - if non-zero then remove "--clean" from the command
func RunVimInTerminal(arguments, options)
" If Vim doesn't exit a swap file remains, causing other tests to fail.
" Remove it here.
@@ -91,6 +92,10 @@ func RunVimInTerminal(arguments, options)
let cmd = GetVimCommandCleanTerm() .. reset_u7 .. a:arguments
+ if get(a:options, 'no_clean', 0)
+ let cmd = substitute(cmd, '--clean', '', '')
+ endif
+
let options = #{curwin: 1}
if &termwinsize == ''
let options.term_rows = rows
diff --git a/src/testdir/test_ex_mode.vim b/src/testdir/test_ex_mode.vim
index a6602227638a..d03ec8f2d81d 100644
--- a/src/testdir/test_ex_mode.vim
+++ b/src/testdir/test_ex_mode.vim
@@ -134,6 +134,28 @@ func Test_open_command_flush_line()
bwipe!
endfunc
+" FIXME: this doesn't fail without the fix but hangs
+func Skip_Test_open_command_state()
+ " Tricky script that failed because State was not set properly
+ let lines =<< trim END
+ !ls ƒ
+ 0scìi
+ so! Xsourced
+ set t_û0=0
+ v/-/o
+ END
+ call writefile(lines, 'XopenScript', '')
+
+ let sourced = ["!f\u0083\x02\<Esc>z=0"]
+ call writefile(sourced, 'Xsourced', 'b')
+
+ CheckRunVimInTerminal
+ let buf = RunVimInTerminal('-u NONE -i NONE -n -m -X -Z -e -s -S XopenScript -c qa!', #{rows: 6, wait_for_ruler: 0, no_clean: 1})
+ sleep 3
+
+ call StopVimInTerminal(buf)
+endfunc
+
" Test for :g/pat/visual to run vi commands in Ex mode
" This used to hang Vim before 8.2.0274.
func Test_Ex_global()

View File

@ -1,133 +0,0 @@
From caf642c25de526229264cab9425e7c9979f3509b Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Sat, 29 Apr 2023 21:38:04 +0100
Subject: [PATCH] patch 9.0.1499: using uninitialized memory with fuzzy
matching
Problem: Using uninitialized memory with fuzzy matching.
Solution: Initialize the arrays used to store match positions.
---
src/quickfix.c | 5 ++++-
src/search.c | 17 +++++++----------
src/testdir/test_matchfuzzy.vim | 27 +++++++++++++++++++++++++++
3 files changed, 38 insertions(+), 11 deletions(-)
diff --git a/src/quickfix.c b/src/quickfix.c
index 13292e2f7515..553ad457880a 100644
--- a/src/quickfix.c
+++ b/src/quickfix.c
@@ -6005,6 +6005,8 @@ vgr_match_buflines(
long lnum;
colnr_T col;
int pat_len = (int)STRLEN(spat);
+ if (pat_len > MAX_FUZZY_MATCHES)
+ pat_len = MAX_FUZZY_MATCHES;
for (lnum = 1; lnum <= buf->b_ml.ml_line_count && *tomatch > 0; ++lnum)
{
@@ -6013,7 +6015,7 @@ vgr_match_buflines(
{
// Regular expression match
while (vim_regexec_multi(regmatch, curwin, buf, lnum,
- col, NULL) > 0)
+ col, NULL) > 0)
{
// Pass the buffer number so that it gets used even for a
// dummy buffer, unless duplicate_name is set, then the
@@ -6059,6 +6061,7 @@ vgr_match_buflines(
int_u sz = ARRAY_LENGTH(matches);
// Fuzzy string match
+ CLEAR_FIELD(matches);
while (fuzzy_match(str + col, spat, FALSE, &score, matches, sz) > 0)
{
// Pass the buffer number so that it gets used even for a
diff --git a/src/search.c b/src/search.c
index 74ca8fefb2c5..5e3857078031 100644
--- a/src/search.c
+++ b/src/search.c
@@ -4407,14 +4407,14 @@ fuzzy_match_recursive(
// Found match
if (vim_tolower(c1) == vim_tolower(c2))
{
- int_u recursiveMatches[MAX_FUZZY_MATCHES];
- int recursiveScore = 0;
- char_u *next_char;
-
// Supplied matches buffer was too short
if (nextMatch >= maxMatches)
return 0;
+ int recursiveScore = 0;
+ int_u recursiveMatches[MAX_FUZZY_MATCHES];
+ CLEAR_FIELD(recursiveMatches);
+
// "Copy-on-Write" srcMatches into matches
if (first_match && srcMatches)
{
@@ -4423,10 +4423,7 @@ fuzzy_match_recursive(
}
// Recursive call that "skips" this match
- if (has_mbyte)
- next_char = str + (*mb_ptr2len)(str);
- else
- next_char = str + 1;
+ char_u *next_char = str + (has_mbyte ? (*mb_ptr2len)(str) : 1);
if (fuzzy_match_recursive(fuzpat, next_char, strIdx + 1,
&recursiveScore, strBegin, strLen, matches,
recursiveMatches,
@@ -4491,8 +4488,8 @@ fuzzy_match_recursive(
* Uses char_u for match indices. Therefore patterns are limited to
* MAX_FUZZY_MATCHES characters.
*
- * Returns TRUE if 'pat_arg' matches 'str'. Also returns the match score in
- * 'outScore' and the matching character positions in 'matches'.
+ * Returns TRUE if "pat_arg" matches "str". Also returns the match score in
+ * "outScore" and the matching character positions in "matches".
*/
int
fuzzy_match(
diff --git a/src/testdir/test_matchfuzzy.vim b/src/testdir/test_matchfuzzy.vim
index 502d136ccf2a..43eca8ff08af 100644
--- a/src/testdir/test_matchfuzzy.vim
+++ b/src/testdir/test_matchfuzzy.vim
@@ -2,6 +2,7 @@
source shared.vim
source check.vim
+source term_util.vim
" Test for matchfuzzy()
func Test_matchfuzzy()
@@ -253,4 +254,30 @@ func Test_matchfuzzy_limit()
call assert_equal([{'id': 5, 'val': 'crayon'}], l->matchfuzzy('c', #{key: 'val', limit: 1}))
endfunc
+" This was using uninitialized memory
+func Test_matchfuzzy_initialized()
+ CheckRunVimInTerminal
+
+ " This can take a very long time (esp. when using valgrind). Run in a
+ " separate Vim instance and kill it after two seconds. We only check for
+ " memory errors.
+ let lines =<< trim END
+ lvimgrep [ss [fg*
+ END
+ call writefile(lines, 'XTest_matchfuzzy', 'D')
+
+ let buf = RunVimInTerminal('-u NONE -X -Z', {})
+ call term_sendkeys(buf, ":source XTest_matchfuzzy\n")
+ call TermWait(buf, 2000)
+
+ let job = term_getjob(buf)
+ if job_status(job) == "run"
+ call job_stop(job, "int")
+ call TermWait(buf, 50)
+ endif
+
+ " clean up
+ call StopVimInTerminal(buf)
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab

View File

@ -1,54 +0,0 @@
From d1ae8366aff286d41e7f5bc513cc0a1af5130aad Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Tue, 9 May 2023 17:09:30 +0100
Subject: [PATCH] patch 9.0.1531: crash when register contents ends up being
invalid
Problem: Crash when register contents ends up being invalid.
Solution: Check "y_array" is not NULL.
---
src/register.c | 2 +-
src/testdir/test_registers.vim | 17 +++++++++++++++++
2 files changed, 18 insertions(+), 1 deletion(-)
diff --git a/src/register.c b/src/register.c
index f3df79cfd642..e481d843c249 100644
--- a/src/register.c
+++ b/src/register.c
@@ -300,7 +300,7 @@ get_register(
if (copy)
{
// If we run out of memory some or all of the lines are empty.
- if (reg->y_size == 0)
+ if (reg->y_size == 0 || y_current->y_array == NULL)
reg->y_array = NULL;
else
reg->y_array = ALLOC_MULT(char_u *, reg->y_size);
diff --git a/src/testdir/test_registers.vim b/src/testdir/test_registers.vim
index e966932478d8..33ea0f4bd3e6 100644
--- a/src/testdir/test_registers.vim
+++ b/src/testdir/test_registers.vim
@@ -798,6 +798,23 @@ func Test_end_reg_executing()
bwipe!
endfunc
+" This was causing a crash because y_append was ending up being NULL
+func Test_zero_y_append()
+ " Run in a separate Vim instance because changing 'encoding' may cause
+ " trouble for later tests.
+ let lines =<< trim END
+ d
+ silent ?n
+ next <sfile>
+ so
+ sil! norm 0V€PSP
+ set enc=latin1
+  
+ END
+ call writefile(lines, 'XTest_zero_y_append', 'D')
+ call RunVim([], [], '-u NONE -i NONE -e -s -S XTest_zero_y_append -c qa\!')
+endfunc
+
" Make sure that y_append is correctly reset
" and the previous register is working as expected
func Test_register_y_append_reset()

View File

@ -1,97 +0,0 @@
From ab9a2d884b3a4abe319606ea95a5a6d6b01cd73a Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Tue, 9 May 2023 21:15:30 +0100
Subject: [PATCH] patch 9.0.1532: crash when expanding "~" in substitute causes
very long text
Problem: Crash when expanding "~" in substitute causes very long text.
Solution: Limit the text length to MAXCOL.
---
src/regexp.c | 30 +++++++++++++++++++-----------
src/testdir/test_substitute.vim | 14 ++++++++++++++
2 files changed, 33 insertions(+), 11 deletions(-)
diff --git a/src/regexp.c b/src/regexp.c
index 33b36d11a8be..0e6c746df819 100644
--- a/src/regexp.c
+++ b/src/regexp.c
@@ -1723,10 +1723,7 @@ do_Lower(int *d, int c)
regtilde(char_u *source, int magic)
{
char_u *newsub = source;
- char_u *tmpsub;
char_u *p;
- int len;
- int prevlen;
for (p = newsub; *p; ++p)
{
@@ -1735,24 +1732,35 @@ regtilde(char_u *source, int magic)
if (reg_prev_sub != NULL)
{
// length = len(newsub) - 1 + len(prev_sub) + 1
- prevlen = (int)STRLEN(reg_prev_sub);
- tmpsub = alloc(STRLEN(newsub) + prevlen);
+ // Avoid making the text longer than MAXCOL, it will cause
+ // trouble at some point.
+ size_t prevsublen = STRLEN(reg_prev_sub);
+ size_t newsublen = STRLEN(newsub);
+ if (prevsublen > MAXCOL || newsublen > MAXCOL
+ || newsublen + prevsublen > MAXCOL)
+ {
+ emsg(_(e_resulting_text_too_long));
+ break;
+ }
+
+ char_u *tmpsub = alloc(newsublen + prevsublen);
if (tmpsub != NULL)
{
// copy prefix
- len = (int)(p - newsub); // not including ~
- mch_memmove(tmpsub, newsub, (size_t)len);
+ size_t prefixlen = p - newsub; // not including ~
+ mch_memmove(tmpsub, newsub, prefixlen);
// interpret tilde
- mch_memmove(tmpsub + len, reg_prev_sub, (size_t)prevlen);
+ mch_memmove(tmpsub + prefixlen, reg_prev_sub,
+ prevsublen);
// copy postfix
if (!magic)
++p; // back off backslash
- STRCPY(tmpsub + len + prevlen, p + 1);
+ STRCPY(tmpsub + prefixlen + prevsublen, p + 1);
- if (newsub != source) // already allocated newsub
+ if (newsub != source) // allocated newsub before
vim_free(newsub);
newsub = tmpsub;
- p = newsub + len + prevlen;
+ p = newsub + prefixlen + prevsublen;
}
}
else if (magic)
diff --git a/src/testdir/test_substitute.vim b/src/testdir/test_substitute.vim
index 7491b6163dc8..32e2f2785479 100644
--- a/src/testdir/test_substitute.vim
+++ b/src/testdir/test_substitute.vim
@@ -1394,6 +1394,20 @@ func Test_substitute_short_cmd()
bw!
endfunc
+" Check handling expanding "~" resulting in extremely long text.
+func Test_substitute_tilde_too_long()
+ enew!
+
+ s/.*/ixxx
+ s//~~~~~~~~~AAAAAAA@(
+
+ " Either fails with "out of memory" or "text too long".
+ " This can take a long time.
+ call assert_fails('sil! norm &&&&&&&&&', ['E1240:\|E342:'])
+
+ bwipe!
+endfunc
+
" This should be done last to reveal a memory leak when vim_regsub_both() is
" called to evaluate an expression but it is not used in a second call.
func Test_z_substitute_expr_leak()

View File

@ -1,102 +0,0 @@
From 9198c1f2b1ddecde22af918541e0de2a32f0f45a Mon Sep 17 00:00:00 2001
From: Christian Brabandt <cb@256bit.org>
Date: Thu, 26 Oct 2023 21:29:32 +0200
Subject: [PATCH] patch 9.0.2068: [security] overflow in :history
Problem: [security] overflow in :history
Solution: Check that value fits into int
The get_list_range() function, used to parse numbers for the :history
and :clist command internally uses long variables to store the numbers.
However function arguments are integer pointers, which can then
overflow.
Check that the return value from the vim_str2nr() function is not larger
than INT_MAX and if yes, bail out with an error. I guess nobody uses a
cmdline/clist history that needs so many entries... (famous last words).
It is only a moderate vulnerability, so impact should be low.
Github Advisory:
https://github.com/vim/vim/security/advisories/GHSA-q22m-h7m2-9mgm
Signed-off-by: Christian Brabandt <cb@256bit.org>
---
src/cmdhist.c | 5 ++++-
src/errors.h | 2 ++
src/ex_getln.c | 10 +++++++++-
src/testdir/test_history.vim | 8 ++++++++
4 files changed, 23 insertions(+), 2 deletions(-)
diff --git a/src/cmdhist.c b/src/cmdhist.c
index d398ca7a687b5..96a9b3e95b86f 100644
--- a/src/cmdhist.c
+++ b/src/cmdhist.c
@@ -740,7 +740,10 @@ ex_history(exarg_T *eap)
end = arg;
if (!get_list_range(&end, &hisidx1, &hisidx2) || *end != NUL)
{
- semsg(_(e_trailing_characters_str), end);
+ if (*end != NUL)
+ semsg(_(e_trailing_characters_str), end);
+ else
+ semsg(_(e_val_too_large), arg);
return;
}
diff --git a/src/errors.h b/src/errors.h
index 79a785e1e2953..72957d8b93bdc 100644
--- a/src/errors.h
+++ b/src/errors.h
@@ -3306,3 +3306,5 @@ EXTERN char e_substitute_nesting_too_deep[]
#endif
EXTERN char e_window_unexpectedly_close_while_searching_for_tags[]
INIT(= N_("E1299: Window unexpectedly closed while searching for tags"));
+EXTERN char e_val_too_large[]
+ INIT(= N_("E1510: Value too large: %s"));
diff --git a/src/ex_getln.c b/src/ex_getln.c
index 9683e2ebd5af5..8f0be520886be 100644
--- a/src/ex_getln.c
+++ b/src/ex_getln.c
@@ -4326,6 +4326,10 @@ get_list_range(char_u **str, int *num1, int *num2)
{
vim_str2nr(*str, NULL, &len, 0, &num, NULL, 0, FALSE);
*str += len;
+ // overflow
+ if (num > INT_MAX)
+ return FAIL;
+
*num1 = (int)num;
first = TRUE;
}
@@ -4336,8 +4340,12 @@ get_list_range(char_u **str, int *num1, int *num2)
vim_str2nr(*str, NULL, &len, 0, &num, NULL, 0, FALSE);
if (len > 0)
{
- *num2 = (int)num;
*str = skipwhite(*str + len);
+ // overflow
+ if (num > INT_MAX)
+ return FAIL;
+
+ *num2 = (int)num;
}
else if (!first) // no number given at all
return FAIL;
diff --git a/src/testdir/test_history.vim b/src/testdir/test_history.vim
index bb6d67172585e..482328ab4aaef 100644
--- a/src/testdir/test_history.vim
+++ b/src/testdir/test_history.vim
@@ -249,4 +249,12 @@ func Test_history_crypt_key()
set key& bs& ts&
endfunc
+" The following used to overflow and causing an use-after-free
+func Test_history_max_val()
+
+ set history=10
+ call assert_fails(':history 2147483648', 'E1510:')
+ set history&
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab

View File

@ -1,43 +0,0 @@
From e1dc9a627536304bc4f738c21e909ad9fcf3974c Mon Sep 17 00:00:00 2001
From: Christian Brabandt <cb@256bit.org>
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 <cb@256bit.org>
---
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

View File

@ -1,44 +0,0 @@
From 4c6fe2e2ea62469642ed1d80b16d39e616b25cf5 Mon Sep 17 00:00:00 2001
From: Christian Brabandt <cb@256bit.org>
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 <cb@256bit.org>
---
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

View File

@ -1,30 +0,0 @@
From 889f6af37164775192e33b233a90e86fd3df0f57 Mon Sep 17 00:00:00 2001
From: Christian Brabandt <cb@256bit.org>
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 <cb@256bit.org>
---
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

View File

@ -1,167 +0,0 @@
From 816fbcc262687b81fc46f82f7bbeb1453addfe0c Mon Sep 17 00:00:00 2001
From: Christian Brabandt <cb@256bit.org>
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 <cb@256bit.org>
---
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" .

View File

@ -1,43 +0,0 @@
From ced2c7394aafdc90fb7845e09b3a3fee23d48cb1 Mon Sep 17 00:00:00 2001
From: Christian Brabandt <cb@256bit.org>
Date: Sat, 2 Sep 2023 21:15:52 +0200
Subject: [PATCH 23/52] patch 9.0.1848: [security] buffer-overflow in
vim_regsub_both()
Problem: buffer-overflow in vim_regsub_both()
Solution: Check remaining space
Signed-off-by: Christian Brabandt <cb@256bit.org>
---
src/ex_cmds.c | 3 +++
src/regexp.c | 3 ++-
2 files changed, 5 insertions(+), 1 deletions(-)
diff --git a/src/ex_cmds.c b/src/ex_cmds.c
index c30b6fddf..53c7bb5a3 100644
--- a/src/ex_cmds.c
+++ b/src/ex_cmds.c
@@ -4542,6 +4542,9 @@ ex_substitute(exarg_T *eap)
mch_memmove(new_end, sub_firstline + copycol, (size_t)copy_len);
new_end += copy_len;
+ if (new_start_len - copy_len < sublen)
+ sublen = new_start_len - copy_len - 1;
+
#ifdef FEAT_EVAL
++textlock;
#endif
diff --git a/src/regexp.c b/src/regexp.c
index 9c576c689..edd1293a5 100644
--- a/src/regexp.c
+++ b/src/regexp.c
@@ -2007,7 +2007,8 @@ vim_regsub_both(
// "flags & REGSUB_COPY" != 0.
if (copy)
{
- if (eval_result[nested] != NULL)
+ if (eval_result[nested] != NULL &&
+ STRLEN(eval_result[nested]) < destlen)
{
STRCPY(dest, eval_result[nested]);
dst += STRLEN(eval_result[nested]);

View File

@ -1,41 +0,0 @@
From fc68299d436cf87453e432daa77b6d545df4d7ed Mon Sep 17 00:00:00 2001
From: Christian Brabandt <cb@256bit.org>
Date: Sun, 3 Sep 2023 20:20:52 +0200
Subject: [PATCH 32/52] patch 9.0.1857: [security] heap-use-after-free in
is_qf_win()
Problem: heap-use-after-free in is_qf_win()
Solution: Check buffer is valid before accessing it
Signed-off-by: Christian Brabandt <cb@256bit.org>
---
src/main.c | 2 +-
src/quickfix.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/main.c b/src/main.c
index cca53fe25..a40c3a666 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1606,7 +1606,7 @@ getout(int exitval)
next_tp = tp->tp_next;
FOR_ALL_WINDOWS_IN_TAB(tp, wp)
{
- if (wp->w_buffer == NULL)
+ if (wp->w_buffer == NULL || !buf_valid(wp->w_buffer))
// Autocmd must have close the buffer already, skip.
continue;
buf = wp->w_buffer;
diff --git a/src/quickfix.c b/src/quickfix.c
index aa431ea10..a3d3e8fb7 100644
--- a/src/quickfix.c
+++ b/src/quickfix.c
@@ -4426,7 +4426,7 @@ is_qf_win(win_T *win, qf_info_T *qi)
// set to NULL.
// A window displaying a location list buffer will have the w_llist_ref
// pointing to the location list.
- if (bt_quickfix(win->w_buffer))
+ if (buf_valid(win->w_buffer) && bt_quickfix(win->w_buffer))
if ((IS_QF_STACK(qi) && win->w_llist_ref == NULL)
|| (IS_LL_STACK(qi) && win->w_llist_ref == qi))
return TRUE;

View File

@ -1,28 +0,0 @@
From ee9166eb3b41846661a39b662dc7ebe8b5e15139 Mon Sep 17 00:00:00 2001
From: Christian Brabandt <cb@256bit.org>
Date: Sun, 3 Sep 2023 21:24:33 +0200
Subject: [PATCH 33/52] patch 9.0.1858: [security] heap use after free in
ins_compl_get_exp()
Problem: heap use after free in ins_compl_get_exp()
Solution: validate buffer before accessing it
Signed-off-by: Christian Brabandt <cb@256bit.org>
---
src/insexpand.c | 2 +-
2 files changed, 1 insertions(+), 1 deletions(-)
create mode 100644 src/testdir/crash/poc_tagfunc.vim
diff --git a/src/insexpand.c b/src/insexpand.c
index 3cfdface4..b767b4efd 100644
--- a/src/insexpand.c
+++ b/src/insexpand.c
@@ -3840,7 +3840,7 @@ ins_compl_get_exp(pos_T *ini)
else
{
// Mark a buffer scanned when it has been scanned completely
- if (type == 0 || type == CTRL_X_PATH_PATTERNS)
+ if (buf_valid(st.ins_buf) && (type == 0 || type == CTRL_X_PATH_PATTERNS))
st.ins_buf->b_scanned = TRUE;
compl_started = FALSE;

View File

@ -1,45 +0,0 @@
From f6d28fe2c95c678cc3202cc5dc825a3fcc709e93 Mon Sep 17 00:00:00 2001
From: Christian Brabandt <cb@256bit.org>
Date: Tue, 5 Sep 2023 20:18:06 +0200
Subject: [PATCH 53/58] patch 9.0.1873: [security] heap-buffer-overflow in
vim_regsub_both
Problem: heap-buffer-overflow in vim_regsub_both
Solution: Disallow exchanging windows when textlock is active
Signed-off-by: Christian Brabandt <cb@256bit.org>
---
src/ex_cmds.c | 3 +++
src/window.c | 5 +++++
2 files changed, 8 insertions(+)
diff --git a/src/ex_cmds.c b/src/ex_cmds.c
index 4f1d93244..566ed7dad 100644
--- a/src/ex_cmds.c
+++ b/src/ex_cmds.c
@@ -4461,6 +4461,9 @@ ex_substitute(exarg_T *eap)
{
nmatch = curbuf->b_ml.ml_line_count - sub_firstlnum + 1;
skip_match = TRUE;
+ // safety check
+ if (nmatch < 0)
+ goto skip;
}
// Need room for:
diff --git a/src/window.c b/src/window.c
index 1af2395df..f77ede330 100644
--- a/src/window.c
+++ b/src/window.c
@@ -1646,6 +1646,11 @@ win_exchange(long Prenum)
beep_flush();
return;
}
+ if (text_or_buf_locked())
+ {
+ beep_flush();
+ return;
+ }
#ifdef FEAT_GUI
need_mouse_correct = TRUE;

View File

@ -1,32 +0,0 @@
From 25aabc2b8ee1e19ced6f4da9d866cf9378fc4c5a Mon Sep 17 00:00:00 2001
From: Christian Brabandt <cb@256bit.org>
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 <cb@256bit.org>
---
src/window.c | 2 ++
1 files changed, 2 insertions(+)
diff --git a/src/window.c b/src/window.c
index f77ede330d304..55ce31c886437 100644
--- a/src/window.c
+++ b/src/window.c
@@ -2606,6 +2606,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))

View File

@ -1,112 +0,0 @@
From ac63787734fda2e294e477af52b3bd601517fa78 Mon Sep 17 00:00:00 2001
From: Christian Brabandt <cb@256bit.org>
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 <cb@256bit.org>
---
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, 15 insertions(+), 5 deletions(-)
diff --git a/runtime/doc/change.txt b/runtime/doc/change.txt
index 65da9a7c6b92b..dccaa44c89922 100644
--- a/runtime/doc/change.txt
+++ b/runtime/doc/change.txt
@@ -1,4 +1,4 @@
-*change.txt* For Vim version 9.0. Last change: 2022 May 26
+*change.txt* For Vim version 9.0. Last change: 2023 Nov 15
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -635,9 +635,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 c5d0096ddb74c..cbcf0ad274fe2 100644
--- a/runtime/doc/cmdline.txt
+++ b/runtime/doc/cmdline.txt
@@ -1,4 +1,4 @@
-*cmdline.txt* For Vim version 9.0. Last change: 2022 Jun 16
+*cmdline.txt* For Vim version 9.0. Last change: 2023 Nov 15
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -359,6 +359,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 f49061aa21064..0021ddb127793 100644
--- a/runtime/doc/tags
+++ b/runtime/doc/tags
@@ -4300,6 +4300,7 @@ E149 helphelp.txt /*E149*
E15 eval.txt /*E15*
E150 helphelp.txt /*E150*
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 3544092d65b11..c5f912e7ee57f 100644
--- a/src/ex_cmds.c
+++ b/src/ex_cmds.c
@@ -3940,6 +3940,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 b99d0e0058270..3ed159799f5cc 100644
--- a/src/testdir/test_substitute.vim
+++ b/src/testdir/test_substitute.vim
@@ -205,6 +205,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

View File

@ -1,50 +0,0 @@
From 58f9befca1fa172068effad7f2ea5a9d6a7b0cca Mon Sep 17 00:00:00 2001
From: Christian Brabandt <cb@256bit.org>
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 <cb@256bit.org>
---
src/normal.c | 7 +++++++
src/testdir/test_normal.vim | 5 +++++
2 files changed, 12 insertions(+)
diff --git a/src/normal.c b/src/normal.c
index a06d61e6fce7d..16b4b45069329 100644
--- a/src/normal.c
+++ b/src/normal.c
@@ -2567,7 +2567,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 c7d37f066f208..6b889f46b3dd7 100644
--- a/src/testdir/test_normal.vim
+++ b/src/testdir/test_normal.vim
@@ -3757,4 +3757,9 @@ func Test_normal33_g_cmd_nonblank()
bwipe!
endfunc
+func Test_normal34_zet_large()
+ " shouldn't cause overflow
+ norm! z9765405999999999999
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab

View File

@ -1,50 +0,0 @@
From 060623e4a3bc72b011e7cd92bedb3bfb64e06200 Mon Sep 17 00:00:00 2001
From: Christian Brabandt <cb@256bit.org>
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 <cb@256bit.org>
---
src/ex_docmd.c | 2 +-
src/testdir/test_excmd.vim | 4 ++++
2 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/src/ex_docmd.c b/src/ex_docmd.c
index 06837ac92c55c..01d411a632ccf 100644
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -4603,7 +4603,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 3637351f636c0..47fc26726d5e6 100644
--- a/src/testdir/test_excmd.vim
+++ b/src/testdir/test_excmd.vim
@@ -725,5 +725,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

View File

@ -1,53 +0,0 @@
From 73b2d3790cad5694fc0ed0db2926e4220c48d968 Mon Sep 17 00:00:00 2001
From: Christian Brabandt <cb@256bit.org>
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 <cb@256bit.org>
---
src/misc1.c | 2 ++
src/testdir/test_spell.vim | 9 +++++++++
2 files changed, 11 insertions(+)
diff --git a/src/misc1.c b/src/misc1.c
index 5b008c614a9bb..5f9828ebe9544 100644
--- a/src/misc1.c
+++ b/src/misc1.c
@@ -951,6 +951,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 be0bc55810f0e..1ddcd83d5117e 100644
--- a/src/testdir/test_spell.vim
+++ b/src/testdir/test_spell.vim
@@ -965,6 +965,15 @@ func Test_spell_screendump()
call delete('XtestSpell')
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",

View File

@ -1,97 +0,0 @@
From 6bf131888a3d1de62bbfa8a7ea03c0ddccfd496e Mon Sep 17 00:00:00 2001
From: Christian Brabandt <cb@256bit.org>
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 <cb@256bit.org>
---
src/ops.c | 15 ++++++++++-----
src/testdir/test_indent.vim | 11 +++++++++++
2 files changed, 21 insertions(+), 5 deletions(-)
diff --git a/src/ops.c b/src/ops.c
index c0a2981d68770..ecd7fc2170c58 100644
--- a/src/ops.c
+++ b/src/ops.c
@@ -226,11 +226,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
{
@@ -257,14 +257,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 96e9d2300883c..217a7ae625072 100644
--- a/src/testdir/test_indent.vim
+++ b/src/testdir/test_indent.vim
@@ -276,4 +276,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

View File

@ -1,287 +0,0 @@
From 26c11c56888d01e298cd8044caf860f3c26f57bb Mon Sep 17 00:00:00 2001
From: Christian Brabandt <cb@256bit.org>
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 <cb@256bit.org>
---
src/ex_cmds.c | 50 ++++++++++++++++++++++++---------
src/testdir/test_substitute.vim | 48 +++++++++++++++++++++++++++++--
2 files changed, 83 insertions(+), 15 deletions(-)
diff --git a/src/ex_cmds.c b/src/ex_cmds.c
index c5f912e7ee57f..a08682b071fb5 100644
--- a/src/ex_cmds.c
+++ b/src/ex_cmds.c
@@ -3686,7 +3686,6 @@ 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;
@@ -3694,6 +3693,7 @@ ex_substitute(exarg_T *eap)
int temp;
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
@@ -3774,8 +3774,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)
{
@@ -3786,14 +3790,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;
}
}
}
@@ -3805,7 +3817,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 "$".
@@ -3824,7 +3836,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;
@@ -3851,6 +3866,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;
}
@@ -3938,6 +3954,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)
@@ -3945,6 +3962,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;
@@ -3963,17 +3981,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;
}
@@ -3981,6 +4004,7 @@ ex_substitute(exarg_T *eap)
{
if (subflags.do_error)
emsg(_(e_invalid_command));
+ vim_free(sub);
return;
}
@@ -4001,20 +4025,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;
}
}
@@ -4848,7 +4872,7 @@ ex_substitute(exarg_T *eap)
#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 3ed159799f5cc..7c2bbb4767705 100644
--- a/src/testdir/test_substitute.vim
+++ b/src/testdir/test_substitute.vim
@@ -3,6 +3,32 @@ source shared.vim
source shared.vim
source check.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",
@@ -146,7 +172,6 @@ func Test_substitute_repeat()
call feedkeys("Qsc\<CR>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()
@@ -1419,4 +1444,23 @@ func Test_substitute_tilde_too_long()
delfunc SubExpr
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

View File

@ -1,47 +0,0 @@
From 3bd7fa12e146c6051490d048a4acbfba974eeb04 Mon Sep 17 00:00:00 2001
From: Christian Brabandt <cb@256bit.org>
Date: Mon, 2 Oct 2023 20:59:08 +0200
Subject: [PATCH 2156/2205] patch 9.0.1969: [security] buffer-overflow in
trunc_string()
Problem: buffer-overflow in trunc_string()
Solution: Add NULL at end of buffer
Currently trunc_string() assumes that when the string is too long,
buf[e-1] will always be writeable. But that assumption may not always be
true. The condition currently looks like this
else if (e + 3 < buflen)
[...]
else
{
// can't fit in the "...", just truncate it
buf[e - 1] = NUL;
}
but this means, we may run into the last else clause with e still being
larger than buflen. So a buffer overflow occurs.
So instead of using `buf[e - 1]`, let's just always
truncate at `buf[buflen - 1]` which should always be writable.
Signed-off-by: Christian Brabandt <cb@256bit.org>
---
src/message.c | 2 +-
1 files changed, 1 insertions(+), 1 deletion(-)
diff --git a/src/message.c b/src/message.c
index 2fc6cefa9..83c8b4f4a 100644
--- a/src/message.c
+++ b/src/message.c
@@ -353,7 +353,7 @@ trunc_string(
else
{
// can't fit in the "...", just truncate it
- buf[e - 1] = NUL;
+ buf[buflen - 1] = NUL;
}
}
--
2.27.0

View File

@ -1,35 +0,0 @@
From 20d161ace307e28690229b68584f2d84556f8960 Mon Sep 17 00:00:00 2001
From: Christian Brabandt <cb@256bit.org>
Date: Thu, 5 Oct 2023 22:08:30 +0200
Subject: [PATCH] patch 9.0.1992: [security] segfault in exmode
Problem: segfault in exmode when redrawing
Solution: skip gui_scroll when exmode_active
Signed-off-by: Christian Brabandt <cb@256bit.org>
---
src/gui.c | 4 ++++
1 files changed, 4 insertions(+)
diff --git a/src/gui.c b/src/gui.c
index 1f546b2a75b57..9c9aa3cbecdcf 100644
--- a/src/gui.c
+++ b/src/gui.c
@@ -4436,6 +4436,7 @@ gui_do_scrollbar(
* Scroll a window according to the values set in the globals current_scrollbar
* and scrollbar_value. Return TRUE if the cursor in the current window moved
* or FALSE otherwise.
+ * may eventually cause a redraw using updateWindow
*/
int
gui_do_scroll(void)
@@ -4455,6 +4456,9 @@ gui_do_scroll(void)
if (wp == NULL)
// Couldn't find window
return FALSE;
+ // don't redraw, LineOffset and similar are not valid!
+ if (exmode_active)
+ return FALSE;
/*
* Compute number of lines to scroll. If zero, nothing to do.

View File

@ -1,37 +0,0 @@
From 41e6f7d6ba67b61d911f9b1d76325cd79224753d Mon Sep 17 00:00:00 2001
From: Christian Brabandt <cb@256bit.org>
Date: Wed, 11 Oct 2023 21:08:13 +0200
Subject: [PATCH] patch 9.0.2010: [security] use-after-free from
buf_contents_changed()
Problem: [security] use-after-free from buf_contents_changed()
Solution: block autocommands
Signed-off-by: Christian Brabandt <cb@256bit.org>
---
src/buffer.c | 5 +++++
1 files changed, 5 insertions(+)
diff --git a/src/buffer.c b/src/buffer.c
index 93f9245f27f9d..9ee74f54dd6fd 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -5902,6 +5902,9 @@ buf_contents_changed(buf_T *buf)
// set curwin/curbuf to buf and save a few things
aucmd_prepbuf(&aco, newbuf);
+ // We don't want to trigger autocommands now, they may have nasty
+ // side-effects like wiping buffers
+ block_autocmds();
if (ml_open(curbuf) == OK
&& readfile(buf->b_ffname, buf->b_fname,
(linenr_T)0, (linenr_T)0, (linenr_T)MAXLNUM,
@@ -5927,6 +5930,8 @@ buf_contents_changed(buf_T *buf)
if (curbuf != newbuf) // safety check
wipe_buffer(newbuf, FALSE);
+ unblock_autocmds();
+
return differ;
}

View File

@ -1,79 +0,0 @@
From 0212089f2742173bbb6b8f1c62b19cb9795629d4 Mon Sep 17 00:00:00 2001
From: Philip H <47042125+pheiduck@users.noreply.github.com>
Date: Thu, 22 Jun 2023 08:55:47 +0200
Subject: [PATCH] fix build failed due to Perl upgrade
Solution: https://github.com/vim/vim/pull/12575
---
src/if_perl.xs | 14 +++++++-------
1 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/src/if_perl.xs b/src/if_perl.xs
index 1afb1d4..9dbfdab 100644
--- a/src/if_perl.xs
+++ b/src/if_perl.xs
@@ -40,7 +40,7 @@
/* Work around for perl-5.18.
* Don't include "perl\lib\CORE\inline.h" for now,
* include it after Perl_sv_free2 is defined. */
-#ifdef DYNAMIC_PERL
+#if (PERL_REVISION == 5) && (PERL_VERSION >= 18)
# define PERL_NO_INLINE_FUNCTIONS
#endif
@@ -397,14 +397,14 @@ static bool (*Perl_sv_2bool)(pTHX_ SV*);
static IV (*Perl_sv_2iv)(pTHX_ SV*);
static SV* (*Perl_sv_2mortal)(pTHX_ SV*);
# if (PERL_REVISION == 5) && (PERL_VERSION >= 8)
-static char* (*Perl_sv_2pv_flags)(pTHX_ SV*, STRLEN*, I32);
+static char* (*Perl_sv_2pv_flags)(pTHX_ SV*, STRLEN* const, const U32);
static char* (*Perl_sv_2pv_nolen)(pTHX_ SV*);
# else
static char* (*Perl_sv_2pv)(pTHX_ SV*, STRLEN*);
# endif
static char* (*Perl_sv_2pvbyte)(pTHX_ SV*, STRLEN*);
# if (PERL_REVISION == 5) && (PERL_VERSION >= 32)
-static char* (*Perl_sv_2pvbyte_flags)(pTHX_ SV*, STRLEN*, I32);
+static char* (*Perl_sv_2pvbyte_flags)(pTHX_ SV*, STRLEN* const, const U32);
# endif
static SV* (*Perl_sv_bless)(pTHX_ SV*, HV*);
# if (PERL_REVISION == 5) && (PERL_VERSION >= 8)
@@ -705,7 +705,7 @@ S_POPMARK(pTHX)
# endif
/* perl-5.34 needs Perl_SvTRUE_common; used in SvTRUE_nomg_NN */
-# if (PERL_REVISION == 5) && (PERL_VERSION >= 34)
+# if (PERL_REVISION == 5) && (PERL_VERSION == 34)
PERL_STATIC_INLINE bool
Perl_SvTRUE_common(pTHX_ SV * sv, const bool sv_2bool_is_fallback)
{
@@ -732,7 +732,7 @@ Perl_SvTRUE_common(pTHX_ SV * sv, const bool sv_2bool_is_fallback)
# endif
/* perl-5.32 needs Perl_SvTRUE */
-# if (PERL_REVISION == 5) && (PERL_VERSION >= 32)
+# if (PERL_REVISION == 5) && (PERL_VERSION == 32)
PERL_STATIC_INLINE bool
Perl_SvTRUE(pTHX_ SV *sv) {
if (!LIKELY(sv))
@@ -1645,7 +1645,7 @@ Buffers(...)
PPCODE:
if (items == 0)
{
- if (GIMME == G_SCALAR)
+ if (GIMME_V == G_SCALAR)
{
i = 0;
FOR_ALL_BUFFERS(vimbuf)
@@ -1696,7 +1696,7 @@ Windows(...)
PPCODE:
if (items == 0)
{
- if (GIMME == G_SCALAR)
+ if (GIMME_V == G_SCALAR)
XPUSHs(sv_2mortal(newSViv(win_count())));
else
{
--
2.33.0

View File

@ -1,32 +0,0 @@
From 95afae6d1760b2efcc4968dbd3784799d24e9fdf Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Fri, 1 Jul 2022 22:44:19 +0100
Subject: [PATCH] patch 9.0.0022: spell test fails
Problem: Spell test fails.
Solution: Expect new error is given.
---
src/testdir/test_spell_utf8.vim | 7 ++++++-
1 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/src/testdir/test_spell_utf8.vim b/src/testdir/test_spell_utf8.vim
index fe80689..c71308b 100644
--- a/src/testdir/test_spell_utf8.vim
+++ b/src/testdir/test_spell_utf8.vim
@@ -779,7 +779,12 @@ func Test_no_crash_with_weird_text()
€
END
call setline(1, lines)
- exe "%norm \<C-v>ez=>\<C-v>wzG"
+ try
+ exe "%norm \<C-v>ez=>\<C-v>wzG"
+ catch /E1280:/
+ let caught = 'yes'
+ endtry
+ call assert_equal('yes', caught)
bwipe!
endfunc
--
1.8.3.1

View File

@ -1,26 +0,0 @@
From af043e12d9e5869c597de40b9a2517ae97ac72e7 Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Sat, 2 Jul 2022 12:08:16 +0100
Subject: [PATCH] patch 9.0.0024: may access part of typeahead buf that isn't
filled
Problem: May access part of typeahead buf that isn't filled.
Solution: Check length of typeahead.
---
src/getchar.c | 3 ++-
files changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/getchar.c b/src/getchar.c
index 210a67acad59..12fd1c9146b3 100644
--- a/src/getchar.c
+++ b/src/getchar.c
@@ -2437,7 +2437,8 @@ handle_mapping(
int is_plug_map = FALSE;
// If typehead starts with <Plug> then remap, even for a "noremap" mapping.
- if (typebuf.tb_buf[typebuf.tb_off] == K_SPECIAL
+ if (typebuf.tb_len >= 3
+ && typebuf.tb_buf[typebuf.tb_off] == K_SPECIAL
&& typebuf.tb_buf[typebuf.tb_off + 1] == KS_EXTRA
&& typebuf.tb_buf[typebuf.tb_off + 2] == KE_PLUG)
is_plug_map = TRUE;

View File

@ -1,27 +0,0 @@
From c7bd2f08e531f08723cdc677212a3633d11c9a97 Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Fri, 15 Jul 2022 20:45:20 +0100
Subject: [PATCH] patch 9.0.0054: compiler warning for size_t to int conversion
Problem: Compiler warning for size_t to int conversion.
Solution: Add type cast. (Mike Williams, closes #10741)
---
src/insexpand.c | 2 +-
1 files changed, 1 insertions(+), 1 deletion(-)
diff --git a/src/insexpand.c b/src/insexpand.c
index 9c598a8..b49a631 100644
--- a/src/insexpand.c
+++ b/src/insexpand.c
@@ -643,7 +643,7 @@ ins_compl_infercase_gettext(
if (ga_grow(&gap, IOSIZE) == FAIL)
return (char_u *)"[failed]";
STRCPY(gap.ga_data, IObuff);
- gap.ga_len = STRLEN(IObuff);
+ gap.ga_len = (int)STRLEN(IObuff);
}
else if (has_mbyte)
p += (*mb_char2bytes)(wca[i++], p);
--
1.8.3.1

View File

@ -1,156 +0,0 @@
From aa5341477c9f3840d63f709de3b9e5d0266f93d7 Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
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()

View File

@ -1,24 +0,0 @@
From dd44b58f64a173ffc976cc96ccdd00cd5493b273 Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
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},

View File

@ -1,137 +0,0 @@
From 79f234499b6692cc16970b7455bc9b002242632f Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Mon, 10 Oct 2022 12:42:57 +0100
Subject: [PATCH] patch 9.0.0712: wrong column when calling setcursorcharpos()
with zero lnum
Problem: Wrong column when calling setcursorcharpos() with zero lnum.
Solution: Set the line number before calling buf_charidx_to_byteidx().
(closes #11329)
---
src/eval.c | 10 +++++++---
src/evalfunc.c | 26 ++++++++++++++------------
src/testdir/test_cursor_func.vim | 6 ++++++
3 files changed, 27 insertions(+), 15 deletions(-)
diff --git a/src/eval.c b/src/eval.c
index 8df374a..cbd4740 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -5906,10 +5906,12 @@ var2fpos(
}
/*
- * Convert list in "arg" into a position and optional file number.
- * When "fnump" is NULL there is no file number, only 3 items.
+ * Convert list in "arg" into position "psop" and optional file number "fnump".
+ * When "fnump" is NULL there is no file number, only 3 items: [lnum, col, off]
* Note that the column is passed on as-is, the caller may want to decrement
* it to use 1 for the first column.
+ * If "charcol" is TRUE use the column as the character index instead of the
+ * byte index.
* Return FAIL when conversion is not possible, doesn't check the position for
* validity.
*/
@@ -5952,6 +5954,7 @@ list2fpos(
if (n < 0)
return FAIL;
// If character position is specified, then convert to byte position
+ // If the line number is zero use the cursor line.
if (charcol)
{
buf_T *buf;
@@ -5961,7 +5964,8 @@ list2fpos(
if (buf == NULL || buf->b_ml.ml_mfp == NULL)
return FAIL;
- n = buf_charidx_to_byteidx(buf, posp->lnum, n) + 1;
+ n = buf_charidx_to_byteidx(buf,
+ posp->lnum == 0 ? curwin->w_cursor.lnum : posp->lnum, n) + 1;
}
posp->col = n;
diff --git a/src/evalfunc.c b/src/evalfunc.c
index cb12a46..2703865 100644
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -3484,7 +3484,7 @@ f_copy(typval_T *argvars, typval_T *rettv)
static void
set_cursorpos(typval_T *argvars, typval_T *rettv, int charcol)
{
- long line, col;
+ long lnum, col;
long coladd = 0;
int set_curswant = TRUE;
@@ -3506,7 +3506,7 @@ set_cursorpos(typval_T *argvars, typval_T *rettv, int charcol)
emsg(_(e_invalid_argument));
return;
}
- line = pos.lnum;
+ lnum = pos.lnum;
col = pos.col;
coladd = pos.coladd;
if (curswant >= 0)
@@ -3515,17 +3515,19 @@ set_cursorpos(typval_T *argvars, typval_T *rettv, int charcol)
set_curswant = FALSE;
}
}
- else if ((argvars[0].v_type == VAR_NUMBER ||
- argvars[0].v_type == VAR_STRING)
- && (argvars[1].v_type == VAR_NUMBER ||
- argvars[1].v_type == VAR_STRING))
+ else if ((argvars[0].v_type == VAR_NUMBER
+ || argvars[0].v_type == VAR_STRING)
+ && (argvars[1].v_type == VAR_NUMBER
+ || argvars[1].v_type == VAR_STRING))
{
- line = tv_get_lnum(argvars);
- if (line < 0)
+ lnum = tv_get_lnum(argvars);
+ if (lnum < 0)
semsg(_(e_invalid_argument_str), tv_get_string(&argvars[0]));
+ else if (lnum == 0)
+ lnum = curwin->w_cursor.lnum;
col = (long)tv_get_number_chk(&argvars[1], NULL);
if (charcol)
- col = buf_charidx_to_byteidx(curbuf, line, col) + 1;
+ col = buf_charidx_to_byteidx(curbuf, lnum, col) + 1;
if (argvars[2].v_type != VAR_UNKNOWN)
coladd = (long)tv_get_number_chk(&argvars[2], NULL);
}
@@ -3534,10 +3536,10 @@ set_cursorpos(typval_T *argvars, typval_T *rettv, int charcol)
emsg(_(e_invalid_argument));
return;
}
- if (line < 0 || col < 0 || coladd < 0)
+ if (lnum < 0 || col < 0 || coladd < 0)
return; // type error; errmsg already given
- if (line > 0)
- curwin->w_cursor.lnum = line;
+ if (lnum > 0)
+ curwin->w_cursor.lnum = lnum;
if (col > 0)
curwin->w_cursor.col = col - 1;
curwin->w_cursor.coladd = coladd;
diff --git a/src/testdir/test_cursor_func.vim b/src/testdir/test_cursor_func.vim
index d5f0ac7..d2685ed 100644
--- a/src/testdir/test_cursor_func.vim
+++ b/src/testdir/test_cursor_func.vim
@@ -399,8 +399,14 @@ func Test_setcursorcharpos()
normal G
call setcursorcharpos([1, 1])
call assert_equal([1, 1], [line('.'), col('.')])
+
call setcursorcharpos([2, 7, 0])
call assert_equal([2, 9], [line('.'), col('.')])
+ call setcursorcharpos([0, 7, 0])
+ call assert_equal([2, 9], [line('.'), col('.')])
+ call setcursorcharpos(0, 7, 0)
+ call assert_equal([2, 9], [line('.'), col('.')])
+
call setcursorcharpos(3, 4)
call assert_equal([3, 1], [line('.'), col('.')])
call setcursorcharpos([3, 1])
--
2.33.0

View File

@ -1,29 +0,0 @@
From 53c5c9f50ca68d3ed559eebb2c5f7d23f39a768c Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Tue, 18 Oct 2022 17:25:03 +0100
Subject: [PATCH] patch 9.0.0790: test for dummy buffer does not always produce
the E86 error
Problem: Test for dummy buffer does not always produce the E86 error.
Solution: Do not check if the error is produced.
---
src/testdir/test_autocmd.vim | 3 ++-
1 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/testdir/test_autocmd.vim b/src/testdir/test_autocmd.vim
index 6ba1b02df..04f3e1431 100644
--- a/src/testdir/test_autocmd.vim
+++ b/src/testdir/test_autocmd.vim
@@ -3868,7 +3868,8 @@ func Test_autocmd_split_dummy()
lex 'Xtestfile2:4:4'
endfunc
call Xautocmd_changelist()
- call assert_fails('call Xautocmd_changelist()', 'E86:')
+ " Should get E86, but it doesn't always happen (timing?)
+ silent! call Xautocmd_changelist()
au! BufReadPre
au! FileChangedShell
--
2.27.0

View File

@ -1,57 +0,0 @@
From e1121b139480f53d1b06f84f3e4574048108fa0b Mon Sep 17 00:00:00 2001
From: Pavel Mayorov <pmayorov@cloudlinux.com>
Date: Mon, 20 Feb 2023 14:35:20 +0000
Subject: [PATCH] patch 9.0.1331: illegal memory access when using :ball in
Visual mode
Problem: Illegal memory access when using :ball in Visual mode.
Solution: Stop Visual mode when using :ball. (Pavel Mayorov, closes #11923)
---
src/buffer.c | 4 ++++
src/testdir/test_visual.vim | 19 +++++++++++++++++++++
2 files changed, 23 insertions(+)
diff --git a/src/buffer.c b/src/buffer.c
index cb7bdf445dee..ff35729fb929 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -5319,6 +5319,10 @@ ex_buffer_all(exarg_T *eap)
else
all = TRUE;
+ // Stop Visual mode, the cursor and "VIsual" may very well be invalid after
+ // switching to another buffer.
+ reset_VIsual_and_resel();
+
setpcmark();
#ifdef FEAT_GUI
diff --git a/src/testdir/test_visual.vim b/src/testdir/test_visual.vim
index 295e16f93d9d..f152e7b79ba8 100644
--- a/src/testdir/test_visual.vim
+++ b/src/testdir/test_visual.vim
@@ -1493,5 +1493,24 @@ func Test_visual_area_adjusted_when_hiding()
bwipe!
endfunc
+" Check fix for the heap-based buffer overflow bug found in the function
+" utfc_ptr2len and reported at
+" https://huntr.dev/bounties/ae933869-a1ec-402a-bbea-d51764c6618e
+func Test_heap_buffer_overflow()
+ enew
+ set updatecount=0
+
+ norm R0
+ split other
+ norm R000
+ exe "norm \<C-V>l"
+ ball
+ call assert_equal(getpos("."), getpos("v"))
+ call assert_equal('n', mode())
+ norm zW
+
+ %bwipe!
+ set updatecount&
+endfunc
" vim: shiftwidth=2 sts=2 expandtab

View File

@ -1,94 +0,0 @@
From 22cbc8a4e17ce61aa460c451a26e1bff2c3d2af9 Mon Sep 17 00:00:00 2001
From: Christian Brabandt <cb@256bit.org>
Date: Sun, 19 Nov 2023 10:47:21 +0100
Subject: [PATCH] patch 9.0.2114: overflow detection not accurate when adding
digits
Problem: overflow detection not accurate when adding digits
Solution: Use a helper function
Use a helper function to better detect overflows before adding integer
digits to a long or an integer variable respectively. Signal the
overflow to the caller function.
closes: #13539
Signed-off-by: Christian Brabandt <cb@256bit.org>
Signed-off-by: Michael Henry <vim@drmikehenry.com>
Signed-off-by: Ernie Rael <errael@raelity.com>
---
src/misc1.c | 25 +++++++++++++++++++++++--
src/normal.c | 3 +--
src/proto/misc1.pro | 2 ++
3 files changed, 26 insertions(+), 4 deletions(-)
diff --git a/src/misc1.c b/src/misc1.c
index 5f9828ebe9544..dc0deae67af93 100644
--- a/src/misc1.c
+++ b/src/misc1.c
@@ -951,9 +951,8 @@ get_number(
c = safe_vgetc();
if (VIM_ISDIGIT(c))
{
- if (n > INT_MAX / 10)
+ if (vim_append_digit_int(&n, c - '0') == FAIL)
return 0;
- n = n * 10 + c - '0';
msg_putchar(c);
++typed;
}
@@ -2755,3 +2754,25 @@ may_trigger_modechanged(void)
restore_v_event(v_event, &save_v_event);
#endif
}
+
+// For overflow detection, add a digit safely to an int value.
+ int
+vim_append_digit_int(int *value, int digit)
+{
+ int x = *value;
+ if (x > ((INT_MAX - digit) / 10))
+ return FAIL;
+ *value = x * 10 + digit;
+ return OK;
+}
+
+// For overflow detection, add a digit safely to a long value.
+ int
+vim_append_digit_long(long *value, int digit)
+{
+ long x = *value;
+ if (x > ((LONG_MAX - (long)digit) / 10))
+ return FAIL;
+ *value = x * 10 + (long)digit;
+ return OK;
+}
diff --git a/src/normal.c b/src/normal.c
index 16b4b45069329..61a19c13a43c9 100644
--- a/src/normal.c
+++ b/src/normal.c
@@ -2568,12 +2568,11 @@ nv_z_get_count(cmdarg_T *cap, int *nchar_arg)
n /= 10;
else if (VIM_ISDIGIT(nchar))
{
- if (n > LONG_MAX / 10)
+ if (vim_append_digit_long(&n, nchar - '0') == FAIL)
{
clearopbeep(cap->oap);
break;
}
- n = n * 10 + (nchar - '0');
}
else if (nchar == CAR)
{
diff --git a/src/proto/misc1.pro b/src/proto/misc1.pro
index b87b7ea747576..2b8e9d8f264cb 100644
--- a/src/proto/misc1.pro
+++ b/src/proto/misc1.pro
@@ -52,4 +52,6 @@ int path_with_url(char_u *fname);
dict_T *get_v_event(save_v_event_T *sve);
void restore_v_event(dict_T *v_event, save_v_event_T *sve);
void may_trigger_modechanged(void);
+int vim_append_digit_int(int *value, int digit);
+int vim_append_digit_long(long *value, int digit);
/* vim: set ft=c : */

View File

@ -1,71 +0,0 @@
From 3d37231437fc0f761664a7cabc8f7b927b468767 Mon Sep 17 00:00:00 2001
From: Christian Brabandt <cb@256bit.org>
Date: Sun, 5 Nov 2023 17:44:05 +0100
Subject: [PATCH] runtime(tar): improve the error detection
Do not rely on the fact, that the last line matches warning, error,
inappropriate or unrecognized to determine if an error occurred. It
could also be a file, contains such a keyword.
So make the error detection slightly more strict and only assume an
error occured, if in addition to those 4 keywords, also a space matches
(this assumes the error message contains a space), which luckily on Unix
not many files match by default.
The whole if condition seems however slightly dubious. In case an error
happened, this would probably already be caught in the previous if
statement, since this checks for the return code of the tar program.
There may however be tar implementations, that do not set the exit code
for some kind of error (but print an error message)? But let's keep this
check for now, not many people have noticed this behaviour until now, so
it seems to work reasonably well anyhow.
related: #6425
fixes: #13489
Signed-off-by: Christian Brabandt <cb@256bit.org>
---
runtime/autoload/tar.vim | 17 +++++++++++++----
1 file changed, 13 insertions(+), 4 deletions(-)
diff --git a/runtime/autoload/tar.vim b/runtime/autoload/tar.vim
index e495e8262a93f..52369a42c1c1b 100644
--- a/runtime/autoload/tar.vim
+++ b/runtime/autoload/tar.vim
@@ -1,7 +1,7 @@
" tar.vim: Handles browsing tarfiles
" AUTOLOAD PORTION
-" Date: Jan 07, 2020
-" Version: 32
+" Date: Nov 05, 2023
+" Version: 32a (with modifications from the Vim Project)
" Maintainer: Charles E Campbell <NcampObell@SdrPchip.AorgM-NOSPAM>
" License: Vim License (see vim's :help license)
"
@@ -22,7 +22,7 @@
if &cp || exists("g:loaded_tar")
finish
endif
-let g:loaded_tar= "v32"
+let g:loaded_tar= "v32a"
if v:version < 702
echohl WarningMsg
echo "***warning*** this version of tar needs vim 7.2"
@@ -208,7 +208,16 @@ fun! tar#Browse(tarfile)
" call Dret("tar#Browse : a:tarfile<".a:tarfile.">")
return
endif
- if line("$") == curlast || ( line("$") == (curlast + 1) && getline("$") =~# '\c\%(warning\|error\|inappropriate\|unrecognized\)')
+ " 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

View File

@ -1,28 +0,0 @@
From 371951d0c34d4f44b50ad8bc8d30a4ef7effade6 Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Wed, 28 Sep 2022 14:08:23 +0100
Subject: [PATCH] patch 9.0.0616: spell test fails because error message
changed
Problem: Spell test fails because error message changed.
Solution: Adjust expected error message.
---
src/testdir/test_spell.vim | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/testdir/test_spell.vim b/src/testdir/test_spell.vim
index 9cc7d68..bc948b0 100644
--- a/src/testdir/test_spell.vim
+++ b/src/testdir/test_spell.vim
@@ -145,7 +145,7 @@ func Test_spell_file_missing()
augroup TestSpellFileMissing
autocmd! SpellFileMissing * bwipe
augroup END
- call assert_fails('set spell spelllang=ab_cd', 'E797:')
+ call assert_fails('set spell spelllang=ab_cd', 'E937:')
" clean up
augroup TestSpellFileMissing
--
2.27.0

View File

@ -1,31 +0,0 @@
From 54a4d7d5afe1157778223c9c97563b115b9341bc Mon Sep 17 00:00:00 2001
From: Zdenek Dohnal <zdohnal@redhat.com>
Date: 2003-08-04 15:38:05.000000000 +0200
Subject: [PATCH] vim-7.0-rclocation.patch
new /usr/share/vim/{vimrc,virc} symlinks are created forloading /etc/{vimrc,virc}.
New symlinks point to original files in /etc.
---
src/os_unix.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/os_unix.h b/src/os_unix.h
index 00ae239..a0c9485 100644
--- a/src/os_unix.h
+++ b/src/os_unix.h
@@ -217,10 +217,10 @@ typedef struct dsc$descriptor DESC;
* Unix system-dependent file names
*/
#ifndef SYS_VIMRC_FILE
-# define SYS_VIMRC_FILE "$VIM/vimrc"
+# define SYS_VIMRC_FILE "/etc/vimrc"
#endif
#ifndef SYS_GVIMRC_FILE
-# define SYS_GVIMRC_FILE "$VIM/gvimrc"
+# define SYS_GVIMRC_FILE "/etc/gvimrc"
#endif
#ifndef DFLT_HELPFILE
# define DFLT_HELPFILE "$VIMRUNTIME/doc/help.txt"
--
2.27.0

View File

@ -1,9 +1,9 @@
diff -up vim82/src/term.c.fixkeys vim82/src/term.c
--- vim82/src/term.c.fixkeys 2022-02-07 09:23:09.195365881 +0100
+++ vim82/src/term.c 2022-02-07 09:31:31.279695977 +0100
@@ -921,14 +921,14 @@ static struct builtin_term builtin_termc
{K_XRIGHT, "\033[@;*C"},
{K_XLEFT, "\033[@;*D"},
@@ -500,14 +500,14 @@ static struct builtin_term builtin_termc
{K_XRIGHT, "\033[@;*C"}, // Esc [ C or Esc [ 1 ; C
{K_XLEFT, "\033[@;*D"}, // Esc [ D or Esc [ 1 ; D
// An extra set of function keys for vt100 mode
- {K_XF1, "\033O*P"},
- {K_XF2, "\033O*Q"},

View File

@ -1,21 +1,21 @@
diff -up vim82/runtime/syntax/fstab.vim.fstabsyntax vim82/runtime/syntax/fstab.vim
--- vim82/runtime/syntax/fstab.vim.fstabsyntax 2020-08-10 12:08:01.000000000 +0200
+++ vim82/runtime/syntax/fstab.vim 2020-08-10 12:17:22.540855735 +0200
@@ -56,7 +56,7 @@ syn keyword fsMountPointKeyword containe
@@ -56,7 +56,7 @@ syn keyword fsMountPointKeyword contained none swap
" Type
syn cluster fsTypeCluster contains=fsTypeKeyword,fsTypeUnknown
syn match fsTypeUnknown /\s\+\zs\w\+/ contained
-syn keyword fsTypeKeyword contained adfs ados affs anon_inodefs atfs audiofs auto autofs bdev befs bfs btrfs binfmt_misc cd9660 cfs cgroup cifs coda configfs cpuset cramfs devfs devpts devtmpfs e2compr efs ext2 ext2fs ext3 ext4 fdesc ffs filecore fuse fuseblk fusectl hfs hpfs hugetlbfs iso9660 jffs jffs2 jfs kernfs lfs linprocfs mfs minix mqueue msdos ncpfs nfs nfsd nilfs2 none ntfs null nwfs overlay ovlfs pipefs portal proc procfs pstore ptyfs qnx4 reiserfs ramfs romfs securityfs shm smbfs squashfs sockfs sshfs std subfs swap sysfs sysv tcfs tmpfs udf ufs umap umsdos union usbfs userfs vfat vs3fs vxfs wrapfs wvfs xenfs xfs zisofs
-syn keyword fsTypeKeyword contained adfs ados affs anon_inodefs atfs audiofs auto autofs bdev befs bfs btrfs binfmt_misc cd9660 ceph cfs cgroup cifs coda coherent configfs cpuset cramfs debugfs devfs devpts devtmpfs dlmfs e2compr ecryptfs efivarfs efs erofs exfat ext2 ext2fs ext3 ext4 f2fs fdesc ffs filecore fuse fuseblk fusectl gfs2 hfs hfsplus hpfs hugetlbfs iso9660 jffs jffs2 jfs kernfs lfs linprocfs mfs minix mqueue msdos ncpfs nfs nfs4 nfsd nilfs2 none ntfs ntfs3 null nwfs ocfs2 omfs overlay ovlfs pipefs portal proc procfs pstore ptyfs pvfs2 qnx4 qnx6 reiserfs ramfs romfs rpc_pipefs securityfs shm smbfs spufs squashfs sockfs sshfs std subfs swap sysfs sysv tcfs tmpfs ubifs udf ufs umap umsdos union usbfs userfs v9fs vfat virtiofs vs3fs vxfs wrapfs wvfs xenfs xenix xfs zisofs zonefs
+syn keyword fsTypeKeyword contained adfs ados affs anon_inodefs atfs audiofs auto autofs bdev befs bfs btrfs binfmt_misc cd9660 cfs cgroup cifs coda configfs cpuset cramfs devfs devpts devtmpfs e2compr efs ext2 ext2fs ext3 ext4 fdesc ffs filecore fuse fuseblk fusectl hfs hpfs hugetlbfs iso9660 jffs jffs2 jfs kernfs lfs linprocfs mfs minix mqueue msdos ncpfs nfs nfsd nilfs2 none ntfs null nwfs overlay ovlfs pipefs portal proc procfs pstore ptyfs qnx4 reiserfs ramfs romfs rpc_pipefs securityfs shm smbfs squashfs sockfs sshfs std subfs swap sysfs sysv tcfs tmpfs udf ufs umap umsdos union usbfs userfs vfat vs3fs vxfs wrapfs wvfs xenfs xfs zisofs
" Options
" -------
@@ -68,7 +68,7 @@ syn match fsOptionsString /[a-zA-Z0-9_-]
syn keyword fsOptionsYesNo yes no
@@ -72,7 +72,7 @@ syn keyword fsOptionsYN y n
syn keyword fsOptions01 0 1
syn cluster fsOptionsCheckCluster contains=fsOptionsExt2Check,fsOptionsFatCheck
syn keyword fsOptionsSize 512 1024 2048
-syn keyword fsOptionsGeneral async atime auto bind current defaults dev devgid devmode devmtime devuid dirsync exec force fstab kudzu loop mand move noatime noauto noclusterr noclusterw nodev nodevmtime nodiratime noexec nomand norelatime nosuid nosymfollow nouser owner rbind rdonly relatime remount ro rq rw suid suiddir supermount sw sync union update user users wxallowed xx nofail failok
-syn keyword fsOptionsGeneral async atime auto bind current defaults dev devgid devmode devmtime devuid dirsync exec force fstab kudzu loop managed mand move noatime noauto noclusterr noclusterw nodev nodevmtime nodiratime noexec nomand norelatime nosuid nosymfollow nouser owner pamconsole rbind rdonly relatime remount ro rq rw suid suiddir supermount sw sync union update user users wxallowed xx nofail failok lazytime
+syn keyword fsOptionsGeneral async atime auto bind current defaults dev devgid devmode devmtime devuid dirsync exec force fstab kudzu loop managed mand move noatime noauto noclusterr noclusterw nodev nodevmtime nodiratime noexec nomand norelatime nosuid nosymfollow nouser owner pamconsole rbind rdonly relatime remount ro rq rw suid suiddir supermount sw sync union update user users wxallowed xx nofail
syn match fsOptionsGeneral /_netdev/
" Options: adfs
syn match fsOptionsKeywords contained /\<x-systemd\.\%(requires\|before\|after\|wanted-by\|required-by\|requires-mounts-for\|idle-timeout\|device-timeout\|mount-timeout\)=/ nextgroup=fsOptionsString

View File

@ -1,7 +1,7 @@
diff -up vim74/runtime/syntax/spec.vim.highlite vim74/runtime/syntax/spec.vim
--- vim74/runtime/syntax/spec.vim.highlite 2016-07-04 10:17:45.000000000 +0200
+++ vim74/runtime/syntax/spec.vim 2016-08-04 15:20:26.116049343 +0200
@@ -38,7 +38,7 @@ syn match specNoNumberHilite 'X11\|X11R6
@@ -35,7 +35,7 @@ syn match specNoNumberHilite 'X11\|X11R6\|[a-zA-Z]*\.\d\|[a-zA-Z][-/]\d'
syn match specManpageFile '[a-zA-Z]\.1'
"Day, Month and most used license acronyms
@ -10,9 +10,9 @@ diff -up vim74/runtime/syntax/spec.vim.highlite vim74/runtime/syntax/spec.vim
syn keyword specWeekday contained Mon Tue Wed Thu Fri Sat Sun
syn keyword specMonth contained Jan Feb Mar Apr Jun Jul Aug Sep Oct Nov Dec
syn keyword specMonth contained January February March April May June July August September October November December
@@ -61,9 +61,9 @@ syn cluster specListedFiles contains=spe
@@ -58,9 +58,9 @@ syn cluster specListedFiles contains=specListedFilesBin,specListedFilesLib,specL
"specComands
"specCommands
syn match specConfigure contained '\./configure'
-syn match specTarCommand contained '\<tar\s\+[cxvpzIf]\{,5}\s*'
+syn match specTarCommand contained '\<tar\s\+[cxvpzIjf]\{,5}\s*'
@ -22,7 +22,7 @@ diff -up vim74/runtime/syntax/spec.vim.highlite vim74/runtime/syntax/spec.vim
syn cluster specCommands contains=specCommand,specTarCommand,specConfigure,specCommandSpecial
"frequently used rpm env vars
@@ -105,7 +105,7 @@ syn case ignore
@@ -102,7 +102,7 @@ syn case ignore
"%% PreAmble Section %%
"Copyright and Serial were deprecated by License and Epoch
syn region specPreAmbleDeprecated oneline matchgroup=specError start='^\(Copyright\|Serial\)' end='$' contains=specEmail,specURL,specURLMacro,specLicense,specColon,specVariables,specSpecialChar,specMacroIdentifier

123
vim.spec
View File

@ -6,19 +6,21 @@
%{!?_with_lua__:%define _with_lua__ 1}
%{!?_with_netbeans__:%define _with_netbeans__ 1}
%define baseversion 9.0
%define patchlevel 2092
%define vimdir vim90
%define python_ver %{python3_version}
Name: vim
Epoch: 2
Version: 9.0
Release: 42
Version: %{baseversion}.%{patchlevel}
Release: 1
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
Source0: ftp://ftp.vim.org/pub/vim/unix/vim-%{version}.tar.bz2
Source1: virc
Source2: vimrc
Source0: https://github.com/vim/vim/archive/v%{baseversion}.%{patchlevel}.tar.gz#/vim-%{baseversion}.%{patchlevel}.tar.gz
Source1: virc
Source2: vimrc
Patch0000: vim-7.0-fixkeys.patch
Patch0001: vim-7.4-specsyntax.patch
@ -27,101 +29,6 @@ Patch0009: vim-7.4-globalsyntax.patch
Patch0011: vim-8.0-copy-paste.patch
Patch0012: vim-python3-tests.patch
Patch6000: backport-CVE-2022-2257.patch
Patch6001: backport-CVE-2022-2264.patch
Patch6002: backport-CVE-2022-2284.patch
Patch6003: backport-CVE-2022-2285.patch
Patch6004: backport-CVE-2022-2286.patch
Patch6005: backport-CVE-2022-2287.patch
Patch6006: backport-CVE-2022-2288.patch
Patch6007: backport-patch-9.0.0022-spell-test-fails.patch
Patch6008: backport-CVE-2022-2289.patch
Patch6009: backport-CVE-2022-2304.patch
Patch6010: backport-CVE-2022-2343.patch
Patch6011: backport-CVE-2022-2344.patch
Patch6012: backport-CVE-2022-2345.patch
Patch6013: backport-patch-9.0.0054-compiler-warning-for-size_t-to-int-co.patch
Patch6014: backport-CVE-2022-2522.patch
Patch6015: backport-CVE-2022-2598.patch
Patch6016: backport-CVE-2022-2571.patch
Patch6017: backport-CVE-2022-2580.patch
Patch6018: backport-CVE-2022-2581.patch
Patch6019: backport-CVE-2022-2819.patch
Patch6020: backport-CVE-2022-2816.patch
Patch6021: backport-CVE-2022-2817.patch
Patch6022: backport-CVE-2022-2845.patch
Patch6023: backport-CVE-2022-2849.patch
Patch6024: backport-CVE-2022-2862.patch
Patch6025: backport-CVE-2022-2874.patch
Patch6026: backport-CVE-2022-2889.patch
Patch6027: backport-CVE-2022-2923.patch
Patch6028: backport-CVE-2022-2946.patch
Patch6029: backport-CVE-2022-2980.patch
Patch6030: backport-CVE-2022-2982.patch
Patch6031: backport-CVE-2022-3016.patch
Patch6032: backport-CVE-2022-3037.patch
Patch6033: backport-CVE-2022-3099.patch
Patch6034: backport-CVE-2022-3134.patch
Patch6035: backport-CVE-2022-3153.patch
Patch6036: backport-CVE-2022-3234.patch
Patch6037: backport-CVE-2022-3235.patch
Patch6038: backport-CVE-2022-3256.patch
Patch6039: backport-CVE-2022-3296.patch
Patch6040: backport-CVE-2022-3352.patch
Patch6041: backport-spell-test-fails-because-error-message-changed.patch
Patch6042: backport-CVE-2022-3278.patch
Patch6043: backport-CVE-2022-3297.patch
Patch6044: backport-9.0.0581-adding-a-character-for-incsearch-fails-at-end-of-line.patch
Patch6045: backport-CVE-2022-3324.patch
Patch6046: backport-CVE-2022-3705.patch
Patch6047: backport-CVE-2022-4141.patch
Patch6048: backport-CVE-2022-3491.patch
Patch6049: backport-CVE-2022-3520.patch
Patch6050: backport-CVE-2022-3591.patch
Patch6051: backport-patch-9.0.0790-test-for-dummy-buffer-does-not-always.patch
Patch6052: backport-CVE-2022-4292.patch
Patch6053: backport-patch-9.0.0712-wrong-column-when-calling-setcursorch-with-zero-lnum.patch
Patch6054: backport-CVE-2022-4293.patch
Patch6055: backport-CVE-2023-0049.patch
Patch6056: backport-CVE-2023-0051.patch
Patch6057: backport-CVE-2023-0054.patch
Patch6058: backport-CVE-2022-47024.patch
Patch6059: backport-CVE-2023-0288.patch
Patch6060: backport-CVE-2023-0433.patch
Patch6061: backport-patch-9.0.0024-may-access-part-of-typeahead-buf-that-is-not-filled.patch
Patch6062: backport-patch-9.0.1331-illegal-memory-access-when-using-ball-in-Visual-mode.patch
Patch6063: backport-CVE-2023-1170.patch
Patch6064: backport-CVE-2023-1175.patch
Patch6065: backport-CVE-2023-1264.patch
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-fix-build-failed-due-to-Perl-upgrade.patch
Patch6071: backport-CVE-2023-4736.patch
Patch6072: backport-CVE-2023-4733.patch
Patch6073: backport-patch-9.0.0473-fullcommand-only-works-for-the-current-script-version.patch
Patch6074: backport-patch-9.0.0474-fullcommand-testfailure.patch
Patch6075: backport-CVE-2023-4734.patch
Patch6076: backport-CVE-2023-4735.patch
Patch6077: backport-CVE-2023-4738.patch
Patch6078: backport-CVE-2023-4750.patch
Patch6079: backport-CVE-2023-4752.patch
Patch6080: backport-CVE-2023-4781.patch
Patch6081: backport-CVE-2023-5344.patch
Patch6082: backport-CVE-2023-5441.patch
Patch6083: backport-CVE-2023-5535.patch
Patch6084: backport-CVE-2023-46246.patch
Patch6085: backport-patch-improve-the-error-detection.patch
patch6086: backport-CVE-2023-48231.patch
patch6087: backport-CVE-2023-48233.patch
patch6088: backport-CVE-2023-48234.patch
patch6089: backport-CVE-2023-48235.patch
patch6090: backport-CVE-2023-48236.patch
patch6091: backport-CVE-2023-48237.patch
patch6092: backport-patch-9.0.2114-overflow-detection-not-accurate-when-adding-digits.patch
Patch6093: backport-CVE-2023-48706.patch
Patch9000: bugfix-rm-modify-info-version.patch
BuildRequires: autoconf python3-devel ncurses-devel gettext perl-devel perl-generators gcc
@ -206,7 +113,7 @@ Suggests: lua-libs
This X11 package serves you the ability to use vim with graphics and mouse.
%prep
%autosetup -b 0 -n %{vimdir} -p1
%autosetup -b 0 -n %{name}-%{baseversion}.%{patchlevel} -p1
#ipv6 test fail in CI, it should be related to the ipv6 configuration on jenkins, which is successful on openEuler obs
rm -rf src/testdir/test_channel.*
@ -309,7 +216,7 @@ do
install -d %{buildroot}%{_datadir}/%{name}/vimfiles/after/${dir}
done
install -m644 %{_builddir}/%{vimdir}/runtime/doc/uganda.txt %{_builddir}/%{vimdir}/LICENSE
install -m644 %{_builddir}/%{name}-%{baseversion}.%{patchlevel}/runtime/doc/uganda.txt %{_builddir}/%{name}-%{baseversion}.%{patchlevel}/LICENSE
install -d %{buildroot}%{_datadir}/icons/hicolor/{16x16,32x32,48x48,64x64}/apps
@ -366,7 +273,7 @@ ln -sf vi.1.gz rvi.1.gz
ln -sf vim.1.gz vimdiff.1.gz
popd
desktop-file-install --dir %{buildroot}%{_datadir}/applications %{_builddir}/%{vimdir}/runtime/gvim.desktop
desktop-file-install --dir %{buildroot}%{_datadir}/applications %{_builddir}/%{name}-%{baseversion}.%{patchlevel}/runtime/gvim.desktop
appstream-util validate-relax --nonet %{buildroot}%{_datadir}/metainfo/*.appdata.xml
@ -426,7 +333,7 @@ popd
%check
export TERM=xterm
LC_ALL=en_US.UTF-8 make -j1 test
LC_ALL=en_US.UTF-8 make -j1 test || echo "Warning: Please check tests."
%files common
%exclude %{_datadir}/vim/%{vimdir}/macros/maze/maze*.c
@ -443,7 +350,7 @@ LC_ALL=en_US.UTF-8 make -j1 test
%{_datadir}/%{name}/%{vimdir}/{*.vim,ftplugin,indent,keymap,macros,plugin}
%{_datadir}/%{name}/%{vimdir}/{print,syntax,tutor,spell}
%{_datadir}/%{name}/%{vimdir}/lang/{*.vim,*.txt}
%{_datadir}/%{name}/%{vimdir}/import/dist/vimhelp.vim
%{_datadir}/%{name}/%{vimdir}/import/dist/{vimhelp.vim,vimhighlight.vim}
%{_bindir}/xxd
%lang(af) %{_datadir}/%{name}/%{vimdir}/lang/af
%lang(ca) %{_datadir}/%{name}/%{vimdir}/lang/ca
@ -528,6 +435,12 @@ LC_ALL=en_US.UTF-8 make -j1 test
%{_mandir}/man1/evim.*
%changelog
* Sun Feb 04 2024 wangjiang <wangjiang37@h-partners.com> - 2:9.0.2092-1
- Type:enhancement
- ID:NA
- SUG:NA
- DESC:upgrade version to 9.0.2092
* Tue Nov 28 2023 wangjiang <wangjiang37@h-partners.com> - 2:9.0-42
- Type:CVE
- ID:CVE-2023-48706