0
0
mirror of https://github.com/vim/vim.git synced 2025-07-26 11:04:33 -04:00

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>
This commit is contained in:
Christian Brabandt 2023-11-14 22:42:59 +01:00
parent 73b2d3790c
commit 6bf131888a
No known key found for this signature in database
GPG Key ID: F3F92DA383FDDE09
3 changed files with 23 additions and 5 deletions

View File

@ -229,11 +229,11 @@ shift_line(
int amount, int amount,
int call_changed_bytes) // call changed_bytes() int call_changed_bytes) // call changed_bytes()
{ {
int count; long long count;
int i, j; int i, j;
int sw_val = (int)get_sw_value_indent(curbuf); 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 if (round) // round off indent
{ {
@ -260,14 +260,19 @@ shift_line(
count = 0; count = 0;
} }
else 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 // Set new indent
if (State & VREPLACE_FLAG) 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 else
(void)set_indent(count, call_changed_bytes ? SIN_CHANGED : 0); (void)set_indent((int)count, call_changed_bytes ? SIN_CHANGED : 0);
} }
/* /*

View File

@ -275,4 +275,15 @@ func Test_formatting_keeps_first_line_indent()
bwipe! bwipe!
endfunc 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 " vim: shiftwidth=2 sts=2 expandtab

View File

@ -704,6 +704,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
2112,
/**/ /**/
2111, 2111,
/**/ /**/