1
0
forked from aniani/vim

patch 8.2.3659: integer overflow with large line number

Problem:    Integer overflow with large line number.
Solution:   Check for overflow. (closes #9202)
This commit is contained in:
Bram Moolenaar
2021-11-24 12:17:53 +00:00
parent 48608b4a4b
commit 03725c5795
6 changed files with 65 additions and 7 deletions

View File

@@ -688,3 +688,5 @@ EXTERN char e_cannot_expand_sfile_in_vim9_function[]
INIT(= N_("E1245: Cannot expand <sfile> in a Vim9 function")); INIT(= N_("E1245: Cannot expand <sfile> in a Vim9 function"));
EXTERN char e_cannot_find_variable_to_unlock_str[] EXTERN char e_cannot_find_variable_to_unlock_str[]
INIT(= N_("E1246: Cannot find variable to (un)lock: %s")); 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"));

View File

@@ -4380,7 +4380,14 @@ get_address(
if (!VIM_ISDIGIT(*cmd)) // '+' is '+1', but '+0' is not '+1' if (!VIM_ISDIGIT(*cmd)) // '+' is '+1', but '+0' is not '+1'
n = 1; n = 1;
else else
{
n = getdigits(&cmd); n = getdigits(&cmd);
if (n == MAXLNUM)
{
emsg(_(e_line_number_out_of_range));
goto error;
}
}
if (addr_type == ADDR_TABS_RELATIVE) if (addr_type == ADDR_TABS_RELATIVE)
{ {
@@ -4404,9 +4411,16 @@ get_address(
if (i == '-') if (i == '-')
lnum -= n; lnum -= n;
else else
{
if (n >= LONG_MAX - lnum)
{
emsg(_(e_line_number_out_of_range));
goto error;
}
lnum += n; lnum += n;
} }
} }
}
} while (*cmd == '/' || *cmd == '?'); } while (*cmd == '/' || *cmd == '?');
error: error:

View File

@@ -630,10 +630,14 @@ getcount:
del_from_showcmd(4); // delete the digit and ~@% del_from_showcmd(4); // delete the digit and ~@%
#endif #endif
} }
else else if (ca.count0 >= 999999999L)
ca.count0 = ca.count0 * 10 + (c - '0'); {
if (ca.count0 < 0) // overflow
ca.count0 = 999999999L; ca.count0 = 999999999L;
}
else
{
ca.count0 = ca.count0 * 10 + (c - '0');
}
#ifdef FEAT_EVAL #ifdef FEAT_EVAL
// Set v:count here, when called from main() and not a stuffed // Set v:count here, when called from main() and not a stuffed
// command, so that v:count can be used in an expression mapping // command, so that v:count can be used in an expression mapping
@@ -700,11 +704,14 @@ getcount:
* multiplied. * multiplied.
*/ */
if (ca.count0) if (ca.count0)
{
if (ca.opcount >= 999999999L / ca.count0)
ca.count0 = 999999999L;
else
ca.count0 *= ca.opcount; ca.count0 *= ca.opcount;
}
else else
ca.count0 = ca.opcount; ca.count0 = ca.opcount;
if (ca.count0 < 0) // overflow
ca.count0 = 999999999L;
} }
/* /*

View File

@@ -655,4 +655,16 @@ func Test_not_break_expression_register()
call assert_equal('1+1', getreg('=', 1)) call assert_equal('1+1', getreg('=', 1))
endfunc 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 " vim: shiftwidth=2 sts=2 expandtab

View File

@@ -3519,4 +3519,25 @@ func Test_normal_gj_on_extra_wide_char()
bw! bw!
endfunc 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 " vim: shiftwidth=2 sts=2 expandtab

View File

@@ -757,6 +757,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 */
/**/
3659,
/**/ /**/
3658, 3658,
/**/ /**/