summaryrefslogtreecommitdiff
path: root/src/register.c
diff options
context:
space:
mode:
authorichizok <gclient.gaap@gmail.com>2021-11-16 12:50:46 +0000
committerBram Moolenaar <Bram@vim.org>2021-11-16 12:50:46 +0000
commitfa53722367c3793fda95dac665af74b8651065e9 (patch)
tree2cef82e26cc0b7ad47dbc154e16c2a03e2777293 /src/register.c
parent314b773abbb9b1ce0020d83482c6daf7ad6a42a2 (diff)
downloadvim-git-fa53722367c3793fda95dac665af74b8651065e9.tar.gz
patch 8.2.3601: check for overflow in put count does not work wellv8.2.3601
Problem: Check for overflow in put count does not work well. Solution: Improve the overflow check. (Ozaki Kiichi, closes #9102)
Diffstat (limited to 'src/register.c')
-rw-r--r--src/register.c62
1 files changed, 35 insertions, 27 deletions
diff --git a/src/register.c b/src/register.c
index 0afa363ec..129c80df8 100644
--- a/src/register.c
+++ b/src/register.c
@@ -1884,18 +1884,30 @@ do_put(
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;
newp = alloc(totlen + oldlen + 1);
if (newp == NULL)
break;
+
// copy part up to cursor to new line
ptr = newp;
mch_memmove(ptr, oldp, (size_t)bd.textcol);
ptr += bd.textcol;
+
// may insert some spaces before the new text
vim_memset(ptr, ' ', (size_t)bd.startspaces);
ptr += bd.startspaces;
+
// insert the new text
for (j = 0; j < count; ++j)
{
@@ -1909,9 +1921,11 @@ do_put(
ptr += spaces;
}
}
+
// may insert some spaces after the new text
vim_memset(ptr, ' ', (size_t)bd.endspaces);
ptr += bd.endspaces;
+
// move the text after the cursor to the end of the line.
mch_memmove(ptr, oldp + bd.textcol + delcount,
(size_t)(oldlen - bd.textcol - delcount + 1));
@@ -2010,26 +2024,20 @@ do_put(
}
}
- do {
-#ifdef FEAT_FLOAT
- double multlen = (double)count * (double)yanklen;
-
+ if (count == 0 || yanklen == 0)
+ {
+ if (VIsual_active)
+ lnum = end_lnum;
+ }
+ else if (count > INT_MAX / yanklen)
+ // multiplication overflow
+ emsg(_(e_resulting_text_too_long));
+ else
+ {
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));
- break;
- }
- else if (totlen > 0)
- {
+ do {
oldp = ml_get(lnum);
+ oldlen = (int)STRLEN(oldp);
if (lnum > start_lnum)
{
pos_T pos;
@@ -2040,12 +2048,12 @@ do_put(
else
col = MAXCOL;
}
- if (VIsual_active && col > (int)STRLEN(oldp))
+ if (VIsual_active && col > oldlen)
{
lnum++;
continue;
}
- newp = alloc(STRLEN(oldp) + totlen + 1);
+ newp = alloc(totlen + oldlen + 1);
if (newp == NULL)
goto end; // alloc() gave an error message
mch_memmove(newp, oldp, (size_t)col);
@@ -2064,13 +2072,13 @@ do_put(
changed_cline_bef_curs();
curwin->w_cursor.col += (colnr_T)(totlen - 1);
}
- }
- if (VIsual_active)
- lnum++;
- } while (VIsual_active && lnum <= end_lnum);
+ if (VIsual_active)
+ lnum++;
+ } while (VIsual_active && lnum <= end_lnum);
- if (VIsual_active) // reset lnum to the last visual line
- lnum--;
+ if (VIsual_active) // reset lnum to the last visual line
+ lnum--;
+ }
curbuf->b_op_end = curwin->w_cursor;
// For "CTRL-O p" in Insert mode, put cursor after last char