!606 backport upstream patch to fix some bugs

From: @wangjiang37 
Reviewed-by: @gaoruoshu 
Signed-off-by: @gaoruoshu
This commit is contained in:
openeuler-ci-bot 2024-05-14 09:53:51 +00:00 committed by Gitee
commit a60f5b131a
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
9 changed files with 782 additions and 6 deletions

View File

@ -0,0 +1,32 @@
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
@@ -2682,6 +2682,8 @@ win_close(win_T *win, int free_buf)
reset_VIsual_and_resel(); // stop Visual mode
other_buffer = TRUE;
+ if (!win_valid(win))
+ return FAIL;
win->w_closing = TRUE;
apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, FALSE, curbuf);
if (!win_valid(win))

View File

@ -0,0 +1,50 @@
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
@@ -2562,7 +2562,14 @@ nv_z_get_count(cmdarg_T *cap, int *nchar_arg)
if (nchar == K_DEL || nchar == K_KDEL)
n /= 10;
else if (VIM_ISDIGIT(nchar))
+ {
+ if (n > LONG_MAX / 10)
+ {
+ clearopbeep(cap->oap);
+ break;
+ }
n = n * 10 + (nchar - '0');
+ }
else if (nchar == CAR)
{
#ifdef FEAT_GUI
diff --git a/src/testdir/test_normal.vim b/src/testdir/test_normal.vim
index c7d37f066f208..6b889f46b3dd7 100644
--- a/src/testdir/test_normal.vim
+++ b/src/testdir/test_normal.vim
@@ -4159,4 +4159,9 @@ func Test_normal33_g_cmd_nonblank()
bw!
endfunc
+func Test_normal34_zet_large()
+ " shouldn't cause overflow
+ norm! z9765405999999999999
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab

View File

@ -0,0 +1,50 @@
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
@@ -4644,7 +4644,7 @@ get_address(
lnum -= n;
else
{
- if (n >= LONG_MAX - lnum)
+ if (lnum >= 0 && n >= LONG_MAX - lnum)
{
emsg(_(e_line_number_out_of_range));
goto error;
diff --git a/src/testdir/test_excmd.vim b/src/testdir/test_excmd.vim
index 3637351f636c0..47fc26726d5e6 100644
--- a/src/testdir/test_excmd.vim
+++ b/src/testdir/test_excmd.vim
@@ -724,5 +724,9 @@ func Test_write_after_rename()
bwipe!
endfunc
+" catch address lines overflow
+func Test_ex_address_range_overflow()
+ call assert_fails(':--+foobar', 'E492:')
+endfunc
" vim: shiftwidth=2 sts=2 expandtab

View File

@ -0,0 +1,53 @@
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
@@ -975,6 +975,8 @@ get_number(
c = safe_vgetc();
if (VIM_ISDIGIT(c))
{
+ if (n > INT_MAX / 10)
+ return 0;
n = n * 10 + c - '0';
msg_putchar(c);
++typed;
diff --git a/src/testdir/test_spell.vim b/src/testdir/test_spell.vim
index be0bc55810f0e..1ddcd83d5117e 100644
--- a/src/testdir/test_spell.vim
+++ b/src/testdir/test_spell.vim
@@ -1077,6 +1077,15 @@ func Test_spell_compatible()
call StopVimInTerminal(buf)
endfunc
+func Test_z_equal_with_large_count()
+ split
+ set spell
+ call setline(1, "ff")
+ norm 0z=337203685477580
+ set nospell
+ bwipe!
+endfunc
+
let g:test_data_aff1 = [
\"SET ISO8859-1",
\"TRY esianrtolcdugmphbyfvkwjkqxz-\xEB\xE9\xE8\xEA\xEF\xEE\xE4\xE0\xE2\xF6\xFC\xFB'ESIANRTOLCDUGMPHBYFVKWJKQXZ",

View File

@ -0,0 +1,97 @@
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
@@ -229,11 +229,11 @@ shift_line(
int amount,
int call_changed_bytes) // call changed_bytes()
{
- int count;
+ long long count;
int i, j;
int sw_val = (int)get_sw_value_indent(curbuf);
- count = get_indent(); // get current indent
+ count = (long long)get_indent(); // get current indent
if (round) // round off indent
{
@@ -260,14 +260,19 @@ shift_line(
count = 0;
}
else
- count += sw_val * amount;
+ {
+ if ((long long)sw_val * (long long)amount > INT_MAX - count)
+ count = INT_MAX;
+ else
+ count += (long long)sw_val * (long long)amount;
+ }
}
// Set new indent
if (State & VREPLACE_FLAG)
- change_indent(INDENT_SET, count, FALSE, NUL, call_changed_bytes);
+ change_indent(INDENT_SET, (int)count, FALSE, NUL, call_changed_bytes);
else
- (void)set_indent(count, call_changed_bytes ? SIN_CHANGED : 0);
+ (void)set_indent((int)count, call_changed_bytes ? SIN_CHANGED : 0);
}
/*
diff --git a/src/testdir/test_indent.vim b/src/testdir/test_indent.vim
index 96e9d2300883c..217a7ae625072 100644
--- a/src/testdir/test_indent.vim
+++ b/src/testdir/test_indent.vim
@@ -275,4 +275,15 @@ func Test_formatting_keeps_first_line_indent()
bwipe!
endfunc
+" Test for indenting with large amount, causes overflow
+func Test_indent_overflow_count()
+ new
+ setl sw=8
+ call setline(1, "abc")
+ norm! V2147483647>
+ " indents by INT_MAX
+ call assert_equal(2147483647, indent(1))
+ close!
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab

View File

@ -0,0 +1,94 @@
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
@@ -975,9 +975,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;
}
@@ -2817,3 +2816,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
@@ -2563,12 +2563,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
@@ -53,4 +53,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

@ -0,0 +1,294 @@
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
@@ -3737,13 +3737,13 @@ ex_substitute(exarg_T *eap)
int save_do_all; // remember user specified 'g' flag
int save_do_ask; // remember user specified 'c' flag
char_u *pat = NULL, *sub = NULL; // init for GCC
- char_u *sub_copy = NULL;
int delimiter;
int sublen;
int got_quit = FALSE;
int got_match = FALSE;
int which_pat;
char_u *cmd;
+ char_u *p;
int save_State;
linenr_T first_line = 0; // first changed line
linenr_T last_line= 0; // below last changed line AFTER the
@@ -3827,8 +3827,12 @@ ex_substitute(exarg_T *eap)
* Small incompatibility: vi sees '\n' as end of the command, but in
* Vim we want to use '\n' to find/substitute a NUL.
*/
- sub = cmd; // remember the start of the substitution
+ p = cmd; // remember the start of the substitution
cmd = skip_substitute(cmd, delimiter);
+ sub = vim_strsave(p);
+ if (sub == NULL)
+ // out of memory
+ return;
if (!eap->skip)
{
@@ -3839,14 +3843,22 @@ ex_substitute(exarg_T *eap)
if (old_sub == NULL) // there is no previous command
{
emsg(_(e_no_previous_substitute_regular_expression));
+ vim_free(sub);
return;
}
- sub = old_sub;
+ vim_free(sub);
+ sub = vim_strsave(old_sub);
+ if (sub == NULL)
+ // out of memory
+ return;
}
else
{
vim_free(old_sub);
old_sub = vim_strsave(sub);
+ if (old_sub == NULL)
+ // out of memory
+ return;
}
}
}
@@ -3858,7 +3870,7 @@ ex_substitute(exarg_T *eap)
return;
}
pat = NULL; // search_regcomp() will use previous pattern
- sub = old_sub;
+ sub = vim_strsave(old_sub);
// Vi compatibility quirk: repeating with ":s" keeps the cursor in the
// last column after using "$".
@@ -3877,7 +3889,10 @@ ex_substitute(exarg_T *eap)
linenr_T joined_lines_count;
if (eap->skip)
+ {
+ vim_free(sub);
return;
+ }
curwin->w_cursor.lnum = eap->line1;
if (*cmd == 'l')
eap->flags = EXFLAG_LIST;
@@ -3904,6 +3919,7 @@ ex_substitute(exarg_T *eap)
save_re_pat(RE_SUBST, pat, magic_isset());
// put pattern in history
add_to_history(HIST_SEARCH, pat, TRUE, NUL);
+ vim_free(sub);
return;
}
@@ -3991,6 +4007,7 @@ ex_substitute(exarg_T *eap)
if (i <= 0 && !eap->skip && subflags.do_error)
{
emsg(_(e_positive_count_required));
+ vim_free(sub);
return;
}
else if (i >= INT_MAX)
@@ -3998,6 +4015,7 @@ ex_substitute(exarg_T *eap)
char buf[20];
vim_snprintf(buf, sizeof(buf), "%ld", i);
semsg(_(e_val_too_large), buf);
+ vim_free(sub);
return;
}
eap->line1 = eap->line2;
@@ -4016,17 +4034,22 @@ ex_substitute(exarg_T *eap)
if (eap->nextcmd == NULL)
{
semsg(_(e_trailing_characters_str), cmd);
+ vim_free(sub);
return;
}
}
if (eap->skip) // not executing commands, only parsing
+ {
+ vim_free(sub);
return;
+ }
if (!subflags.do_count && !curbuf->b_p_ma)
{
// Substitution is not allowed in non-'modifiable' buffer
emsg(_(e_cannot_make_changes_modifiable_is_off));
+ vim_free(sub);
return;
}
@@ -4034,6 +4057,7 @@ ex_substitute(exarg_T *eap)
{
if (subflags.do_error)
emsg(_(e_invalid_command));
+ vim_free(sub);
return;
}
@@ -4054,20 +4078,20 @@ ex_substitute(exarg_T *eap)
*/
if (sub[0] == '\\' && sub[1] == '=')
{
- sub = vim_strsave(sub);
- if (sub == NULL)
+ p = vim_strsave(sub);
+ vim_free(sub);
+ if (p == NULL)
return;
- sub_copy = sub;
+ sub = p;
}
else
{
- char_u *newsub = regtilde(sub, magic_isset());
+ p = regtilde(sub, magic_isset());
- if (newsub != sub)
+ if (p != sub)
{
- // newsub was allocated, free it later.
- sub_copy = newsub;
- sub = newsub;
+ vim_free(sub);
+ sub = p;
}
}
@@ -4965,7 +4989,7 @@ 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
@@ -4,6 +4,32 @@ source shared.vim
source check.vim
source screendump.vim
+" NOTE: This needs to be the first test to be
+" run in the file, since it depends on
+" that the previous substitution atom
+" was not yet set.
+"
+" recursive call of :s and sub-replace special
+" (did cause heap-use-after free in < v9.0.2121)
+func Test_aaaa_substitute_expr_recursive_special()
+ func R()
+ " FIXME: leaving out the 'n' flag leaks memory, why?
+ %s/./\='.'/gn
+ endfunc
+ new Xfoobar_UAF
+ put ='abcdef'
+ let bufnr = bufnr('%')
+ try
+ silent! :s/./~\=R()/0
+ "call assert_fails(':s/./~\=R()/0', 'E939:')
+ let @/='.'
+ ~g
+ catch /^Vim\%((\a\+)\)\=:E565:/
+ endtry
+ delfunc R
+ exe bufnr .. "bw!"
+endfunc
+
func Test_multiline_subst()
enew!
call append(0, ["1 aa",
@@ -147,7 +173,6 @@ func Test_substitute_repeat()
call feedkeys("Qsc\<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()
@@ -1447,11 +1472,30 @@ func Test_substitute_expr_switch_win()
endfunc
new Xfoobar
let bufnr = bufnr('%')
- put ="abcdef"
+ put ='abcdef'
silent! s/\%')/\=R()
call assert_fails(':%s/./\=R()/g', 'E565:')
delfunc R
exe bufnr .. "bw!"
endfunc
+" recursive call of :s using test-replace special
+func Test_substitute_expr_recursive()
+ func Q()
+ %s/./\='foobar'/gn
+ return "foobar"
+ endfunc
+ func R()
+ %s/./\=Q()/g
+ endfunc
+ new Xfoobar_UAF
+ let bufnr = bufnr('%')
+ put ='abcdef'
+ silent! s/./\=R()/g
+ call assert_fails(':%s/./\=R()/g', 'E565:')
+ delfunc R
+ delfunc Q
+ exe bufnr .. "bw!"
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab

View File

@ -0,0 +1,90 @@
From df63da98d8dc284b1c76cfe1b17fa0acbd6094d8 Mon Sep 17 00:00:00 2001
From: Christian Brabandt <cb@256bit.org>
Date: Thu, 23 Nov 2023 20:14:28 +0100
Subject: [PATCH] patch 9.0.2123: Problem with initializing the length of
range() lists
Problem: Problem with initializing the length of range() lists
Solution: Set length explicitly when it shouldn't contain any items
range() may cause a wrong calculation of list length, which may later
then cause a segfault in list_find(). This is usually not a problem,
because range_list_materialize() calculates the length, when it
materializes the list.
In addition, in list_find() when the length of the range was wrongly
initialized, it may seem to be valid, so the check for list index
out-of-bounds will not be true, because it is called before the list is
actually materialized. And so we may eventually try to access a null
pointer, causing a segfault.
So this patch does 3 things:
- In f_range(), when we know that the list should be empty, explicitly
set the list->lv_len value to zero. This should happen, when
start is larger than end (in case the stride is positive) or
end is larger than start when the stride is negative.
This should fix the underlying issue properly. However,
- as a safety measure, let's check that the requested index is not
out of range one more time, after the list has been materialized
and return NULL in case it suddenly is.
- add a few more tests to verify the behaviour.
fixes: #13557
closes: #13563
Co-authored-by: Tim Pope <tpope@github.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
---
src/evalfunc.c | 5 ++++-
src/list.c | 4 ++++
src/testdir/test_functions.vim | 3 +++
3 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/src/evalfunc.c b/src/evalfunc.c
index 7f7914eca7d91..fa27d0d274a64 100644
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -8646,7 +8646,10 @@ f_range(typval_T *argvars, typval_T *rettv)
list->lv_u.nonmat.lv_start = start;
list->lv_u.nonmat.lv_end = end;
list->lv_u.nonmat.lv_stride = stride;
- list->lv_len = (end - start) / stride + 1;
+ if (stride > 0 ? end < start : end > start)
+ list->lv_len = 0;
+ else
+ list->lv_len = (end - start) / stride + 1;
}
/*
diff --git a/src/list.c b/src/list.c
index d1494c67d56e9..ce1ccaa1c045c 100644
--- a/src/list.c
+++ b/src/list.c
@@ -415,6 +415,10 @@ list_find(list_T *l, long n)
CHECK_LIST_MATERIALIZE(l);
+ // range_list_materialize may reset l->lv_len
+ if (n >= l->lv_len)
+ return NULL;
+
// When there is a cached index may start search from there.
if (l->lv_u.mat.lv_idx_item != NULL)
{
diff --git a/src/testdir/test_functions.vim b/src/testdir/test_functions.vim
index 49b688c25f347..0801d2b695b76 100644
--- a/src/testdir/test_functions.vim
+++ b/src/testdir/test_functions.vim
@@ -3052,6 +3052,9 @@ func Test_range()
" get()
call assert_equal(4, get(range(1, 10), 3))
call assert_equal(-1, get(range(1, 10), 42, -1))
+ call assert_equal(0, get(range(1, 0, 2), 0))
+ call assert_equal(0, get(range(0, -1, 2), 0))
+ call assert_equal(0, get(range(-2, -1, -2), 0))
" index()
call assert_equal(1, index(range(1, 5), 2))

View File

@ -14,7 +14,7 @@
Name: vim
Epoch: 2
Version: %{baseversion}.%{patchlevel}
Release: 2
Release: 3
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
@ -24,11 +24,21 @@ Source2: vimrc
Patch0000: vim-7.0-fixkeys.patch
Patch0001: vim-7.4-specsyntax.patch
Patch0006: vim-7.4-fstabsyntax.patch
Patch0009: vim-7.4-globalsyntax.patch
Patch0011: vim-8.0-copy-paste.patch
Patch0012: vim-python3-tests.patch
Patch0013: bugfix-security-overflow-with-count-for-s-command.patch
Patch0002: vim-7.4-fstabsyntax.patch
Patch0003: vim-7.4-globalsyntax.patch
Patch0004: vim-8.0-copy-paste.patch
Patch0005: vim-python3-tests.patch
Patch6000: bugfix-security-overflow-with-count-for-s-command.patch
Patch6001: backport-patch-9.0.2106-Use-after-free-in-win_close.patch
Patch6002: backport-patch-9.0.2109-overflow-in-nv_z_get_count.patch
Patch6003: backport-patch-9.0.2110-overflow-in-ex-address-parsing.patch
Patch6004: backport-patch-9.0.2111-overflow-in-get_number.patch
Patch6005: backport-patch-9.0.2112-overflow-in-shift_line.patch
Patch6006: backport-patch-9.0.2114-overflow-detection-not-accurate-when-adding.patch
Patch6007: backport-patch-9.0.2121-use-after-free-in-ex_substitute.patch
Patch6008: backport-patch-9.0.2123-Problem-with-initializing-the-length-of-range-lists.patch
Patch9000: bugfix-rm-modify-info-version.patch
@ -436,6 +446,12 @@ LC_ALL=en_US.UTF-8 make -j1 test || echo "Warning: Please check tests."
%{_mandir}/man1/evim.*
%changelog
* Sat May 11 2024 wangjiang <wangjiang37@h-partners.com> - 2:9.0.2092-3
- Type:bugfix
- ID:NA
- SUG:NA
- DESC:backport upstream patch to fix some bugs
* Wed May 08 2024 yinyongkang <yinyongkang@kylinos.cn> - 2:9.0.2092-2
- Type:bugfix
- ID:NA