forked from aniani/vim
patch 8.2.3601: check for overflow in put count does not work well
Problem: Check for overflow in put count does not work well. Solution: Improve the overflow check. (Ozaki Kiichi, closes #9102)
This commit is contained in:
@@ -1884,18 +1884,30 @@ do_put(
|
|||||||
spaces = 0;
|
spaces = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// insert the new text
|
// Insert the new text.
|
||||||
|
// First check for multiplication overflow.
|
||||||
|
if (yanklen + spaces != 0
|
||||||
|
&& count > ((INT_MAX - (bd.startspaces + bd.endspaces))
|
||||||
|
/ (yanklen + spaces)))
|
||||||
|
{
|
||||||
|
emsg(_(e_resulting_text_too_long));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
totlen = count * (yanklen + spaces) + bd.startspaces + bd.endspaces;
|
totlen = count * (yanklen + spaces) + bd.startspaces + bd.endspaces;
|
||||||
newp = alloc(totlen + oldlen + 1);
|
newp = alloc(totlen + oldlen + 1);
|
||||||
if (newp == NULL)
|
if (newp == NULL)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// copy part up to cursor to new line
|
// copy part up to cursor to new line
|
||||||
ptr = newp;
|
ptr = newp;
|
||||||
mch_memmove(ptr, oldp, (size_t)bd.textcol);
|
mch_memmove(ptr, oldp, (size_t)bd.textcol);
|
||||||
ptr += bd.textcol;
|
ptr += bd.textcol;
|
||||||
|
|
||||||
// may insert some spaces before the new text
|
// may insert some spaces before the new text
|
||||||
vim_memset(ptr, ' ', (size_t)bd.startspaces);
|
vim_memset(ptr, ' ', (size_t)bd.startspaces);
|
||||||
ptr += bd.startspaces;
|
ptr += bd.startspaces;
|
||||||
|
|
||||||
// insert the new text
|
// insert the new text
|
||||||
for (j = 0; j < count; ++j)
|
for (j = 0; j < count; ++j)
|
||||||
{
|
{
|
||||||
@@ -1909,9 +1921,11 @@ do_put(
|
|||||||
ptr += spaces;
|
ptr += spaces;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// may insert some spaces after the new text
|
// may insert some spaces after the new text
|
||||||
vim_memset(ptr, ' ', (size_t)bd.endspaces);
|
vim_memset(ptr, ' ', (size_t)bd.endspaces);
|
||||||
ptr += bd.endspaces;
|
ptr += bd.endspaces;
|
||||||
|
|
||||||
// move the text after the cursor to the end of the line.
|
// move the text after the cursor to the end of the line.
|
||||||
mch_memmove(ptr, oldp + bd.textcol + delcount,
|
mch_memmove(ptr, oldp + bd.textcol + delcount,
|
||||||
(size_t)(oldlen - bd.textcol - delcount + 1));
|
(size_t)(oldlen - bd.textcol - delcount + 1));
|
||||||
@@ -2010,26 +2024,20 @@ do_put(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
if (count == 0 || yanklen == 0)
|
||||||
#ifdef FEAT_FLOAT
|
|
||||||
double multlen = (double)count * (double)yanklen;
|
|
||||||
|
|
||||||
totlen = count * yanklen;
|
|
||||||
if ((double)totlen != multlen)
|
|
||||||
#else
|
|
||||||
long multlen = count * yanklen;
|
|
||||||
|
|
||||||
// this only works when sizeof(int) != sizeof(long)
|
|
||||||
totlen = multlen;
|
|
||||||
if (totlen != multlen)
|
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
emsg(_(e_resulting_text_too_long));
|
if (VIsual_active)
|
||||||
break;
|
lnum = end_lnum;
|
||||||
}
|
}
|
||||||
else if (totlen > 0)
|
else if (count > INT_MAX / yanklen)
|
||||||
|
// multiplication overflow
|
||||||
|
emsg(_(e_resulting_text_too_long));
|
||||||
|
else
|
||||||
{
|
{
|
||||||
|
totlen = count * yanklen;
|
||||||
|
do {
|
||||||
oldp = ml_get(lnum);
|
oldp = ml_get(lnum);
|
||||||
|
oldlen = (int)STRLEN(oldp);
|
||||||
if (lnum > start_lnum)
|
if (lnum > start_lnum)
|
||||||
{
|
{
|
||||||
pos_T pos;
|
pos_T pos;
|
||||||
@@ -2040,12 +2048,12 @@ do_put(
|
|||||||
else
|
else
|
||||||
col = MAXCOL;
|
col = MAXCOL;
|
||||||
}
|
}
|
||||||
if (VIsual_active && col > (int)STRLEN(oldp))
|
if (VIsual_active && col > oldlen)
|
||||||
{
|
{
|
||||||
lnum++;
|
lnum++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
newp = alloc(STRLEN(oldp) + totlen + 1);
|
newp = alloc(totlen + oldlen + 1);
|
||||||
if (newp == NULL)
|
if (newp == NULL)
|
||||||
goto end; // alloc() gave an error message
|
goto end; // alloc() gave an error message
|
||||||
mch_memmove(newp, oldp, (size_t)col);
|
mch_memmove(newp, oldp, (size_t)col);
|
||||||
@@ -2064,13 +2072,13 @@ do_put(
|
|||||||
changed_cline_bef_curs();
|
changed_cline_bef_curs();
|
||||||
curwin->w_cursor.col += (colnr_T)(totlen - 1);
|
curwin->w_cursor.col += (colnr_T)(totlen - 1);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (VIsual_active)
|
if (VIsual_active)
|
||||||
lnum++;
|
lnum++;
|
||||||
} while (VIsual_active && lnum <= end_lnum);
|
} while (VIsual_active && lnum <= end_lnum);
|
||||||
|
|
||||||
if (VIsual_active) // reset lnum to the last visual line
|
if (VIsual_active) // reset lnum to the last visual line
|
||||||
lnum--;
|
lnum--;
|
||||||
|
}
|
||||||
|
|
||||||
curbuf->b_op_end = curwin->w_cursor;
|
curbuf->b_op_end = curwin->w_cursor;
|
||||||
// For "CTRL-O p" in Insert mode, put cursor after last char
|
// For "CTRL-O p" in Insert mode, put cursor after last char
|
||||||
|
@@ -149,8 +149,16 @@ func Test_p_with_count_leaves_mark_at_end()
|
|||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
func Test_very_large_count()
|
func Test_very_large_count()
|
||||||
if v:sizeofint != 8
|
new
|
||||||
throw 'Skipped: only works with 64 bit ints'
|
" total put-length (21474837 * 100) brings 32 bit int overflow
|
||||||
|
let @" = repeat('x', 100)
|
||||||
|
call assert_fails('norm 21474837p', 'E1240:')
|
||||||
|
bwipe!
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
func Test_very_large_count_64bit()
|
||||||
|
if v:sizeoflong < 8
|
||||||
|
throw 'Skipped: only works with 64 bit long ints'
|
||||||
endif
|
endif
|
||||||
|
|
||||||
new
|
new
|
||||||
@@ -159,6 +167,27 @@ func Test_very_large_count()
|
|||||||
bwipe!
|
bwipe!
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
func Test_very_large_count_block()
|
||||||
|
new
|
||||||
|
" total put-length (21474837 * 100) brings 32 bit int overflow
|
||||||
|
call setline(1, repeat('x', 100))
|
||||||
|
exe "norm \<C-V>99ly"
|
||||||
|
call assert_fails('norm 21474837p', 'E1240:')
|
||||||
|
bwipe!
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
func Test_very_large_count_block_64bit()
|
||||||
|
if v:sizeoflong < 8
|
||||||
|
throw 'Skipped: only works with 64 bit long ints'
|
||||||
|
endif
|
||||||
|
|
||||||
|
new
|
||||||
|
call setline(1, 'x')
|
||||||
|
exe "norm \<C-V>y"
|
||||||
|
call assert_fails('norm 44444444444444p', 'E1240:')
|
||||||
|
bwipe!
|
||||||
|
endfunc
|
||||||
|
|
||||||
func Test_put_above_first_line()
|
func Test_put_above_first_line()
|
||||||
new
|
new
|
||||||
let @" = 'text'
|
let @" = 'text'
|
||||||
|
@@ -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 */
|
||||||
|
/**/
|
||||||
|
3601,
|
||||||
/**/
|
/**/
|
||||||
3600,
|
3600,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user