patch 9.0.2112: [security]: overflow in shift_line

Commit: 
https://github.com/vim/vim/commit/6bf131888a3d1de62bbfa8a7ea03c0ddccfd496e
Author: Christian Brabandt <[email protected]>
Date:   Tue Nov 14 22:42:59 2023 +0100

    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 <[email protected]>

diff --git a/src/ops.c b/src/ops.c
index c0a2981d6..ecd7fc217 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 96e9d2300..217a7ae62 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
diff --git a/src/version.c b/src/version.c
index 66aff800b..249cd11d2 100644
--- a/src/version.c
+++ b/src/version.c
@@ -704,6 +704,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    2112,
 /**/
     2111,
 /**/

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/E1r3jhj-00DAIS-9e%40256bit.org.

Raspunde prin e-mail lui