]> granicus.if.org Git - vim/commitdiff
patch 8.2.3659: integer overflow with large line number v8.2.3659
authorBram Moolenaar <Bram@vim.org>
Wed, 24 Nov 2021 12:17:53 +0000 (12:17 +0000)
committerBram Moolenaar <Bram@vim.org>
Wed, 24 Nov 2021 12:17:53 +0000 (12:17 +0000)
Problem:    Integer overflow with large line number.
Solution:   Check for overflow. (closes #9202)

src/errors.h
src/ex_docmd.c
src/normal.c
src/testdir/test_excmd.vim
src/testdir/test_normal.vim
src/version.c

index cde98461ec2deed0c70487192f77beb3ac2a0953..6346bf249a272d394d6b87038e5d1ccb59a3bce0 100644 (file)
@@ -688,3 +688,5 @@ EXTERN char e_cannot_expand_sfile_in_vim9_function[]
        INIT(= N_("E1245: Cannot expand <sfile> in a Vim9 function"));
 EXTERN char e_cannot_find_variable_to_unlock_str[]
        INIT(= N_("E1246: Cannot find variable to (un)lock: %s"));
+EXTERN char e_line_number_out_of_range[]
+       INIT(= N_("E1247: Line number out of range"));
index 76511de703faa88be9762d37309bbc05b8bc14b9..d74ef90263f66f535611474060bbcf86237ea99c 100644 (file)
@@ -4380,7 +4380,14 @@ get_address(
            if (!VIM_ISDIGIT(*cmd))     // '+' is '+1', but '+0' is not '+1'
                n = 1;
            else
+           {
                n = getdigits(&cmd);
+               if (n == MAXLNUM)
+               {
+                   emsg(_(e_line_number_out_of_range));
+                   goto error;
+               }
+           }
 
            if (addr_type == ADDR_TABS_RELATIVE)
            {
@@ -4398,13 +4405,20 @@ get_address(
                // Relative line addressing, need to adjust for folded lines
                // now, but only do it after the first address.
                if (addr_type == ADDR_LINES && (i == '-' || i == '+')
-                       && address_count >= 2)
+                                                        && address_count >= 2)
                    (void)hasFolding(lnum, NULL, &lnum);
 #endif
                if (i == '-')
                    lnum -= n;
                else
+               {
+                   if (n >= LONG_MAX - lnum)
+                   {
+                       emsg(_(e_line_number_out_of_range));
+                       goto error;
+                   }
                    lnum += n;
+               }
            }
        }
     } while (*cmd == '/' || *cmd == '?');
index 56fae51dacf25c750a97aed79859e327a92bc2b0..adce93205720100cb2628354ddc425e9c2e2dee0 100644 (file)
@@ -630,10 +630,14 @@ getcount:
                del_from_showcmd(4);    // delete the digit and ~@%
 #endif
            }
+           else if (ca.count0 >= 999999999L)
+           {
+               ca.count0 = 999999999L;
+           }
            else
+           {
                ca.count0 = ca.count0 * 10 + (c - '0');
-           if (ca.count0 < 0)      // overflow
-               ca.count0 = 999999999L;
+           }
 #ifdef FEAT_EVAL
            // Set v:count here, when called from main() and not a stuffed
            // command, so that v:count can be used in an expression mapping
@@ -700,11 +704,14 @@ getcount:
         * multiplied.
         */
        if (ca.count0)
-           ca.count0 *= ca.opcount;
+       {
+           if (ca.opcount >= 999999999L / ca.count0)
+               ca.count0 = 999999999L;
+           else
+               ca.count0 *= ca.opcount;
+       }
        else
            ca.count0 = ca.opcount;
-       if (ca.count0 < 0)          // overflow
-           ca.count0 = 999999999L;
     }
 
     /*
index 773a1a33e14460ea590248f9fde513a3a8c1217d..67b95bb3bdbcac4dc33e48abc70894dffa40842b 100644 (file)
@@ -655,4 +655,16 @@ func Test_not_break_expression_register()
   call assert_equal('1+1', getreg('=', 1))
 endfunc
 
+func Test_address_line_overflow()
+  if v:sizeoflong < 8
+    throw 'Skipped: only works with 64 bit long ints'
+  endif
+  new
+  call setline(1, 'text')
+  call assert_fails('|.44444444444444444444444', 'E1247:')
+  call assert_fails('|.9223372036854775806', 'E1247:')
+  bwipe!
+endfunc
+
+
 " vim: shiftwidth=2 sts=2 expandtab
index e17aca4128d733e346ec5ec1f026008185a2ab24..732456df669da7dc488f972f5ac5ba50348427c4 100644 (file)
@@ -3519,4 +3519,25 @@ func Test_normal_gj_on_extra_wide_char()
   bw!
 endfunc
 
+func Test_normal_count_out_of_range()
+  new
+  call setline(1, 'text')
+  normal 44444444444|
+  call assert_equal(999999999, v:count)
+  normal 444444444444|
+  call assert_equal(999999999, v:count)
+  normal 4444444444444|
+  call assert_equal(999999999, v:count)
+  normal 4444444444444444444|
+  call assert_equal(999999999, v:count)
+
+  normal 9y99999999|
+  call assert_equal(899999991, v:count)
+  normal 10y99999999|
+  call assert_equal(999999999, v:count)
+  normal 44444444444y44444444444|
+  call assert_equal(999999999, v:count)
+  bwipe!
+endfunc
+
 " vim: shiftwidth=2 sts=2 expandtab
index a261ebd4531396a4b6cae339a679ee3d2ab05032..c56391f3560912bcac6bc1eba68fbe9dcfea6534 100644 (file)
@@ -757,6 +757,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    3659,
 /**/
     3658,
 /**/