mirror of
https://github.com/neovim/neovim.git
synced 2024-12-19 02:34:59 -07:00
vim-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: vim/vim#13535
6bf131888a
Skip the test for now, as it takes too long and requires other fixes.
Co-authored-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
parent
4889935a7a
commit
2336389d23
@ -283,11 +283,11 @@ void shift_line(bool left, bool round, int amount, int call_changed_bytes)
|
||||
if (sw_val == 0) {
|
||||
sw_val = 1; // shouldn't happen, just in case
|
||||
}
|
||||
int count = get_indent(); // get current indent
|
||||
int64_t count = get_indent(); // get current indent
|
||||
|
||||
if (round) { // round off indent
|
||||
int i = count / sw_val; // number of 'shiftwidth' rounded down
|
||||
int j = count % sw_val; // extra spaces
|
||||
int i = (int)(count / sw_val); // number of 'shiftwidth' rounded down
|
||||
int j = (int)(count % sw_val); // extra spaces
|
||||
if (j && left) { // first remove extra spaces
|
||||
amount--;
|
||||
}
|
||||
@ -301,15 +301,19 @@ void shift_line(bool left, bool round, int amount, int call_changed_bytes)
|
||||
if (left) {
|
||||
count = MAX(count - sw_val * amount, 0);
|
||||
} else {
|
||||
count += sw_val * amount;
|
||||
if ((int64_t)sw_val * (int64_t)amount > INT_MAX - count) {
|
||||
count = INT_MAX;
|
||||
} else {
|
||||
count += (int64_t)sw_val * (int64_t)amount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set new indent
|
||||
if (State & VREPLACE_FLAG) {
|
||||
change_indent(INDENT_SET, count, false, call_changed_bytes);
|
||||
change_indent(INDENT_SET, (int)count, false, call_changed_bytes);
|
||||
} else {
|
||||
set_indent(count, call_changed_bytes ? SIN_CHANGED : 0);
|
||||
set_indent((int)count, call_changed_bytes ? SIN_CHANGED : 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -276,4 +276,16 @@ func Test_formatting_keeps_first_line_indent()
|
||||
bwipe!
|
||||
endfunc
|
||||
|
||||
" Test for indenting with large amount, causes overflow
|
||||
func Test_indent_overflow_count()
|
||||
throw 'skipped: TODO: '
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user