aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBilly Su <g4691821@gmail.com>2019-03-02 12:38:36 +0800
committerBilly Su <g4691821@gmail.com>2019-03-07 23:48:53 +0800
commitfbd8209286373843b7e9b4151a1432fc4555484d (patch)
treeed434d5f07975fe4bc4b52ba401254e55b7c523d /src
parent570e41fc08ae80421c2458d90cd14d7c3ba65d76 (diff)
downloadrneovim-fbd8209286373843b7e9b4151a1432fc4555484d.tar.gz
rneovim-fbd8209286373843b7e9b4151a1432fc4555484d.tar.bz2
rneovim-fbd8209286373843b7e9b4151a1432fc4555484d.zip
vim-patch:8.0.0645: no error for illegal back reference in NFA engine
Problem: The new regexp engine does not give an error for using a back reference where it is not allowed. (Dominique Pelle) Solution: Check the back reference like the old engine. (closes vim/vim#1774) https://github.com/vim/vim/commit/1ef9bbe215e13a273e74fccaddd8fc5a42c76b6e
Diffstat (limited to 'src')
-rw-r--r--src/nvim/regexp.c44
-rw-r--r--src/nvim/regexp_nfa.c10
-rw-r--r--src/nvim/testdir/test_hlsearch.vim4
-rw-r--r--src/nvim/testdir/test_regexp_latin.vim10
-rw-r--r--src/nvim/testdir/test_statusline.vim2
5 files changed, 48 insertions, 22 deletions
diff --git a/src/nvim/regexp.c b/src/nvim/regexp.c
index 25fa67c112..396b376e39 100644
--- a/src/nvim/regexp.c
+++ b/src/nvim/regexp.c
@@ -1210,6 +1210,31 @@ char_u *skip_regexp(char_u *startp, int dirc, int magic, char_u **newp)
return p;
}
+/*
+ * Return TRUE if the back reference is legal. We must have seen the close
+ * brace.
+ * TODO: Should also check that we don't refer to something that is repeated
+ * (+*=): what instance of the repetition should we match?
+ */
+static int seen_endbrace(int refnum)
+{
+ if (!had_endbrace[refnum]) {
+ char_u *p;
+
+ /* Trick: check if "@<=" or "@<!" follows, in which case
+ * the \1 can appear before the referenced match. */
+ for (p = regparse; *p != NUL; ++p)
+ if (p[0] == '@' && p[1] == '<' && (p[2] == '!' || p[2] == '='))
+ break;
+
+ if (*p == NUL) {
+ EMSG(_("E65: Illegal back reference"));
+ rc_did_emsg = TRUE;
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
/*
* bt_regcomp() - compile a regular expression into internal code for the
@@ -1928,23 +1953,8 @@ static char_u *regatom(int *flagp)
int refnum;
refnum = c - Magic('0');
- /*
- * Check if the back reference is legal. We must have seen the
- * close brace.
- * TODO: Should also check that we don't refer to something
- * that is repeated (+*=): what instance of the repetition
- * should we match?
- */
- if (!had_endbrace[refnum]) {
- /* Trick: check if "@<=" or "@<!" follows, in which case
- * the \1 can appear before the referenced match. */
- for (p = regparse; *p != NUL; ++p)
- if (p[0] == '@' && p[1] == '<'
- && (p[2] == '!' || p[2] == '='))
- break;
- if (*p == NUL)
- EMSG_RET_NULL(_("E65: Illegal back reference"));
- }
+ if (!seen_endbrace(refnum))
+ return NULL;
ret = regnode(BACKREF + refnum);
}
break;
diff --git a/src/nvim/regexp_nfa.c b/src/nvim/regexp_nfa.c
index 0df67336d3..c44e0c9979 100644
--- a/src/nvim/regexp_nfa.c
+++ b/src/nvim/regexp_nfa.c
@@ -1338,8 +1338,14 @@ static int nfa_regatom(void)
case Magic('7'):
case Magic('8'):
case Magic('9'):
- EMIT(NFA_BACKREF1 + (no_Magic(c) - '1'));
- nfa_has_backref = TRUE;
+ {
+ int refnum = no_Magic(c) - '1';
+
+ if (!seen_endbrace(refnum + 1))
+ return FAIL;
+ EMIT(NFA_BACKREF1 + refnum);
+ nfa_has_backref = TRUE;
+ }
break;
case Magic('z'):
diff --git a/src/nvim/testdir/test_hlsearch.vim b/src/nvim/testdir/test_hlsearch.vim
index dd0b05da98..18c4cb37b4 100644
--- a/src/nvim/testdir/test_hlsearch.vim
+++ b/src/nvim/testdir/test_hlsearch.vim
@@ -37,11 +37,11 @@ func Test_hlsearch_hangs()
return
endif
- " This pattern takes forever to match, it should timeout.
+ " This pattern takes a long time to match, it should timeout.
help
let start = reltime()
set hlsearch nolazyredraw redrawtime=101
- let @/ = '\%#=2\v(a|\1)*'
+ let @/ = '\%#=1a*.*X\@<=b*'
redraw
let elapsed = reltimefloat(reltime(start))
call assert_true(elapsed > 0.1)
diff --git a/src/nvim/testdir/test_regexp_latin.vim b/src/nvim/testdir/test_regexp_latin.vim
index 8f9b1eb7ca..0619e9c027 100644
--- a/src/nvim/testdir/test_regexp_latin.vim
+++ b/src/nvim/testdir/test_regexp_latin.vim
@@ -63,3 +63,13 @@ func Test_rex_init()
bwipe!
set re=0
endfunc
+
+func Test_backref()
+ new
+ call setline(1, ['one', 'two', 'three', 'four', 'five'])
+ call assert_equal(3, search('\%#=1\(e\)\1'))
+ call assert_equal(3, search('\%#=2\(e\)\1'))
+ call assert_fails('call search("\\%#=1\\(e\\1\\)")', 'E65:')
+ call assert_fails('call search("\\%#=2\\(e\\1\\)")', 'E65:')
+ bwipe!
+endfunc
diff --git a/src/nvim/testdir/test_statusline.vim b/src/nvim/testdir/test_statusline.vim
index cf85bd58ac..351b119acd 100644
--- a/src/nvim/testdir/test_statusline.vim
+++ b/src/nvim/testdir/test_statusline.vim
@@ -223,7 +223,7 @@ func Test_statusline()
set statusline=ab%(cd%q%)de
call assert_match('^abde\s*$', s:get_statusline())
copen
- call assert_match('^abcd\[Quickfix List\1]de\s*$', s:get_statusline())
+ call assert_match('^abcd\[Quickfix List]de\s*$', s:get_statusline())
cclose
" %#: Set highlight group. The name must follow and then a # again.