diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/ex_cmds.c | 10 | ||||
-rw-r--r-- | src/nvim/globals.h | 2 | ||||
-rw-r--r-- | src/nvim/pos.h | 4 | ||||
-rw-r--r-- | src/nvim/testdir/test_retab.vim | 21 |
4 files changed, 35 insertions, 2 deletions
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index fd1e34803f..49bf9972b1 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -814,7 +814,11 @@ void ex_retab(exarg_T *eap) // len is actual number of white characters used len = num_spaces + num_tabs; old_len = (long)STRLEN(ptr); - long new_len = old_len - col + start_col + len + 1; + const long new_len = old_len - col + start_col + len + 1; + if (new_len <= 0 || new_len >= MAXCOL) { + emsg(_(e_resulting_text_too_long)); + break; + } new_line = xmalloc(new_len); if (start_col > 0) { @@ -847,6 +851,10 @@ void ex_retab(exarg_T *eap) break; } vcol += win_chartabsize(curwin, ptr + col, (colnr_T)vcol); + if (vcol >= MAXCOL) { + emsg(_(e_resulting_text_too_long)); + break; + } col += utfc_ptr2len(ptr + col); } if (new_line == NULL) { // out of memory diff --git a/src/nvim/globals.h b/src/nvim/globals.h index f6fbe98ff0..98a38c5fe2 100644 --- a/src/nvim/globals.h +++ b/src/nvim/globals.h @@ -1000,6 +1000,8 @@ EXTERN char e_non_empty_string_required[] INIT(= N_("E1142: Non-empty string req EXTERN char e_cannot_define_autocommands_for_all_events[] INIT(= N_("E1155: Cannot define autocommands for ALL events")); +EXTERN char e_resulting_text_too_long[] INIT(= N_("E1240: Resulting text too long")); + EXTERN char e_highlight_group_name_too_long[] INIT(= N_("E1249: Highlight group name too long")); EXTERN char top_bot_msg[] INIT(= N_("search hit TOP, continuing at BOTTOM")); diff --git a/src/nvim/pos.h b/src/nvim/pos.h index d17e27906e..51991ed314 100644 --- a/src/nvim/pos.h +++ b/src/nvim/pos.h @@ -16,7 +16,9 @@ typedef int colnr_T; /// Maximal (invalid) line number enum { MAXLNUM = 0x7fffffff, }; /// Maximal column number -enum { MAXCOL = INT_MAX, }; +/// MAXCOL used to be INT_MAX, but with 64 bit ints that results in running +/// out of memory when trying to allocate a very long line. +enum { MAXCOL = 0x7fffffff, }; // Minimum line number enum { MINLNUM = 1, }; // minimum column number diff --git a/src/nvim/testdir/test_retab.vim b/src/nvim/testdir/test_retab.vim index e7b8946ccf..1650a03876 100644 --- a/src/nvim/testdir/test_retab.vim +++ b/src/nvim/testdir/test_retab.vim @@ -69,6 +69,8 @@ func Test_retab() call assert_equal(" a b c ", Retab('!', 3)) call assert_equal(" a b c ", Retab('', 5)) call assert_equal(" a b c ", Retab('!', 5)) + + set tabstop& expandtab& endfunc func Test_retab_error() @@ -78,3 +80,22 @@ func Test_retab_error() call assert_fails('ret 10000', 'E475:') call assert_fails('ret 80000000000000000000', 'E475:') endfunc + +func Test_retab_endless() + new + call setline(1, "\t0\t") + let caught = 'no' + try + while 1 + set ts=4000 + retab 4 + endwhile + catch /E1240/ + let caught = 'yes' + endtry + bwipe! + set tabstop& +endfunc + + +" vim: shiftwidth=2 sts=2 expandtab |