98 lines
3.0 KiB
Diff
98 lines
3.0 KiB
Diff
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
|