aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJustin M. Keyes <justinkz@gmail.com>2019-03-01 02:32:13 +0100
committerGitHub <noreply@github.com>2019-03-01 02:32:13 +0100
commit085f0f1b1b4e03d5378ca37ae2cb8670a7fa53cd (patch)
treef479fb2d53d16ce5779354c13467fa158759d730
parente7bd49d835e26c96b2ee152e5b697e20ab749650 (diff)
parente116b0f61f87a79fd93beb32c337f5bd9e2d3ab9 (diff)
downloadrneovim-085f0f1b1b4e03d5378ca37ae2cb8670a7fa53cd.tar.gz
rneovim-085f0f1b1b4e03d5378ca37ae2cb8670a7fa53cd.tar.bz2
rneovim-085f0f1b1b4e03d5378ca37ae2cb8670a7fa53cd.zip
Merge #9653 from justinmk/vim-8.1.0985
-rw-r--r--src/nvim/misc1.c3
-rw-r--r--src/nvim/regexp.c39
-rw-r--r--src/nvim/regexp_nfa.c22
-rw-r--r--src/nvim/testdir/test_search.vim61
4 files changed, 95 insertions, 30 deletions
diff --git a/src/nvim/misc1.c b/src/nvim/misc1.c
index e752910a4b..a8cfc2d700 100644
--- a/src/nvim/misc1.c
+++ b/src/nvim/misc1.c
@@ -1819,6 +1819,9 @@ void changed(void)
changed_int();
}
buf_inc_changedtick(curbuf);
+
+ // If a pattern is highlighted, the position may now be invalid.
+ highlight_match = false;
}
/*
diff --git a/src/nvim/regexp.c b/src/nvim/regexp.c
index 53479294de..3b3ca29dad 100644
--- a/src/nvim/regexp.c
+++ b/src/nvim/regexp.c
@@ -2098,18 +2098,20 @@ static char_u *regatom(int *flagp)
default: i = -1; break;
}
- if (i < 0)
- EMSG2_RET_NULL(
- _("E678: Invalid character after %s%%[dxouU]"),
- reg_magic == MAGIC_ALL);
- if (use_multibytecode(i))
+ if (i < 0 || i > INT_MAX) {
+ EMSG2_RET_NULL(_("E678: Invalid character after %s%%[dxouU]"),
+ reg_magic == MAGIC_ALL);
+ }
+ if (use_multibytecode(i)) {
ret = regnode(MULTIBYTECODE);
- else
+ } else {
ret = regnode(EXACTLY);
- if (i == 0)
+ }
+ if (i == 0) {
regc(0x0a);
- else
+ } else {
regmbc(i);
+ }
regc(NUL);
*flagp |= HASWIDTH;
break;
@@ -3063,10 +3065,10 @@ static int coll_get_char(void)
case 'u': nr = gethexchrs(4); break;
case 'U': nr = gethexchrs(8); break;
}
- if (nr < 0) {
- /* If getting the number fails be backwards compatible: the character
- * is a backslash. */
- --regparse;
+ if (nr < 0 || nr > INT_MAX) {
+ // If getting the number fails be backwards compatible: the character
+ // is a backslash.
+ regparse--;
nr = '\\';
}
return nr;
@@ -7088,6 +7090,7 @@ regprog_T *vim_regcomp(char_u *expr_arg, int re_flags)
{
regprog_T *prog = NULL;
char_u *expr = expr_arg;
+ int save_called_emsg;
regexp_engine = p_re;
@@ -7114,9 +7117,11 @@ regprog_T *vim_regcomp(char_u *expr_arg, int re_flags)
bt_regengine.expr = expr;
nfa_regengine.expr = expr;
- /*
- * First try the NFA engine, unless backtracking was requested.
- */
+ //
+ // First try the NFA engine, unless backtracking was requested.
+ //
+ save_called_emsg = called_emsg;
+ called_emsg = false;
if (regexp_engine != BACKTRACKING_ENGINE) {
prog = nfa_regengine.regcomp(expr,
re_flags + (regexp_engine == AUTOMATIC_ENGINE ? RE_AUTO : 0));
@@ -7141,11 +7146,13 @@ regprog_T *vim_regcomp(char_u *expr_arg, int re_flags)
// If the NFA engine failed, try the backtracking engine. The NFA engine
// also fails for patterns that it can't handle well but are still valid
// patterns, thus a retry should work.
- if (regexp_engine == AUTOMATIC_ENGINE) {
+ // But don't try if an error message was given.
+ if (regexp_engine == AUTOMATIC_ENGINE && !called_emsg) {
regexp_engine = BACKTRACKING_ENGINE;
prog = bt_regengine.regcomp(expr, re_flags);
}
}
+ called_emsg |= save_called_emsg;
if (prog != NULL) {
// Store the info needed to call regcomp() again when the engine turns out
diff --git a/src/nvim/regexp_nfa.c b/src/nvim/regexp_nfa.c
index d34e653058..95030974d8 100644
--- a/src/nvim/regexp_nfa.c
+++ b/src/nvim/regexp_nfa.c
@@ -1420,12 +1420,12 @@ static int nfa_regatom(void)
default: nr = -1; break;
}
- if (nr < 0)
- EMSG2_RET_FAIL(
- _("E678: Invalid character after %s%%[dxouU]"),
- reg_magic == MAGIC_ALL);
- /* A NUL is stored in the text as NL */
- /* TODO: what if a composing character follows? */
+ if (nr < 0 || nr > INT_MAX) {
+ EMSG2_RET_FAIL(_("E678: Invalid character after %s%%[dxouU]"),
+ reg_magic == MAGIC_ALL);
+ }
+ // A NUL is stored in the text as NL
+ // TODO(vim): what if a composing character follows?
EMIT(nr == 0 ? 0x0a : nr);
}
break;
@@ -6476,16 +6476,10 @@ static regprog_T *nfa_regcomp(char_u *expr, int re_flags)
nfa_regcomp_start(expr, re_flags);
- /* Build postfix form of the regexp. Needed to build the NFA
- * (and count its size). */
+ // Build postfix form of the regexp. Needed to build the NFA
+ // (and count its size).
postfix = re2post();
if (postfix == NULL) {
- // TODO(vim): only give this error for debugging?
- if (post_ptr >= post_end) {
- IEMSGN("Internal error: estimated max number "
- "of states insufficient: %" PRId64,
- post_end - post_start);
- }
goto fail; // Cascaded (syntax?) error
}
diff --git a/src/nvim/testdir/test_search.vim b/src/nvim/testdir/test_search.vim
index 9e2f80fcba..08ccc8d4fe 100644
--- a/src/nvim/testdir/test_search.vim
+++ b/src/nvim/testdir/test_search.vim
@@ -489,6 +489,30 @@ func Test_incsearch_substitute_dump()
call delete('Xis_subst_script')
endfunc
+func Test_incsearch_with_change()
+ if !has('timers') || !exists('+incsearch') || !CanRunVimInTerminal()
+ return
+ endif
+
+ call writefile([
+ \ 'set incsearch hlsearch scrolloff=0',
+ \ 'call setline(1, ["one", "two ------ X", "three"])',
+ \ 'call timer_start(200, { _ -> setline(2, "x")})',
+ \ ], 'Xis_change_script')
+ let buf = RunVimInTerminal('-S Xis_change_script', {'rows': 9, 'cols': 70})
+ " Give Vim a chance to redraw to get rid of the spaces in line 2 caused by
+ " the 'ambiwidth' check.
+ sleep 300m
+
+ " Highlight X, it will be deleted by the timer callback.
+ call term_sendkeys(buf, ':%s/X')
+ call VerifyScreenDump(buf, 'Test_incsearch_change_01', {})
+ call term_sendkeys(buf, "\<Esc>")
+
+ call StopVimInTerminal(buf)
+ call delete('Xis_change_script')
+endfunc
+
func Test_search_undefined_behaviour()
if !has("terminal")
return
@@ -524,3 +548,40 @@ func Test_search_sentence()
/\%'(
/
endfunc
+
+func Test_large_hex_chars1()
+ " This used to cause a crash, the character becomes an NFA state.
+ try
+ /\%Ufffffc23
+ catch
+ call assert_match('E678:', v:exception)
+ endtry
+ try
+ set re=1
+ /\%Ufffffc23
+ catch
+ call assert_match('E678:', v:exception)
+ endtry
+ set re&
+endfunc
+
+func Test_large_hex_chars2()
+ " This used to cause a crash, the character becomes an NFA state.
+ try
+ /[\Ufffffc1f]
+ catch
+ call assert_match('E486:', v:exception)
+ endtry
+ try
+ set re=1
+ /[\Ufffffc1f]
+ catch
+ call assert_match('E486:', v:exception)
+ endtry
+ set re&
+endfunc
+
+func Test_one_error_msg()
+ " This was also giving an internal error
+ call assert_fails('call search(" \\((\\v[[=P=]]){185}+ ")', 'E871:')
+endfunc