To: vim_dev@googlegroups.com Subject: Patch 8.2.3601 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.3601 Problem: Check for overflow in put count does not work well. Solution: Improve the overflow check. (Ozaki Kiichi, closes #9102) Files: src/register.c, src/testdir/test_put.vim *** ../vim-8.2.3600/src/register.c 2021-11-02 23:10:56.930903622 +0000 --- src/register.c 2021-11-16 12:47:56.944799820 +0000 *************** *** 1884,1901 **** spaces = 0; } ! // insert the new text 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) { --- 1884,1913 ---- spaces = 0; } ! // 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,1917 **** --- 1921,1931 ---- 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,2035 **** } } ! do { ! #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)); ! break; ! } ! else if (totlen > 0) ! { oldp = ml_get(lnum); if (lnum > start_lnum) { pos_T pos; --- 2024,2043 ---- } } ! 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; ! do { oldp = ml_get(lnum); + oldlen = (int)STRLEN(oldp); if (lnum > start_lnum) { pos_T pos; *************** *** 2040,2051 **** else col = MAXCOL; } ! if (VIsual_active && col > (int)STRLEN(oldp)) { lnum++; continue; } ! newp = alloc(STRLEN(oldp) + totlen + 1); if (newp == NULL) goto end; // alloc() gave an error message mch_memmove(newp, oldp, (size_t)col); --- 2048,2059 ---- else col = MAXCOL; } ! if (VIsual_active && col > oldlen) { lnum++; continue; } ! newp = alloc(totlen + oldlen + 1); if (newp == NULL) goto end; // alloc() gave an error message mch_memmove(newp, oldp, (size_t)col); *************** *** 2064,2076 **** 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) // 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 --- 2072,2084 ---- 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) // 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 *** ../vim-8.2.3600/src/testdir/test_put.vim 2021-11-04 15:10:07.357074257 +0000 --- src/testdir/test_put.vim 2021-11-16 12:42:27.281157120 +0000 *************** *** 149,156 **** endfunc func Test_very_large_count() ! if v:sizeofint != 8 ! throw 'Skipped: only works with 64 bit ints' endif new --- 149,164 ---- endfunc func Test_very_large_count() ! new ! " 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 new *************** *** 158,163 **** --- 166,192 ---- call assert_fails('norm 44444444444444p', 'E1240:') bwipe! 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 \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 \y" + call assert_fails('norm 44444444444444p', 'E1240:') + bwipe! + endfunc func Test_put_above_first_line() new *** ../vim-8.2.3600/src/version.c 2021-11-16 11:53:09.453121747 +0000 --- src/version.c 2021-11-16 12:44:58.577003578 +0000 *************** *** 759,760 **** --- 759,762 ---- { /* Add new patch number below this line */ + /**/ + 3601, /**/ -- ARTHUR: Shut up! Will you shut up! DENNIS: Ah, now we see the violence inherent in the system. ARTHUR: Shut up! DENNIS: Oh! Come and see the violence inherent in the system! HELP! HELP! I'm being repressed! The Quest for the Holy Grail (Monty Python) /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// \\\ \\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///