Skip to content

Commit 1ef9bbe

Browse files
committed
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 #1774)
1 parent 5b1affe commit 1ef9bbe

File tree

6 files changed

+53
-23
lines changed

6 files changed

+53
-23
lines changed

src/regexp.c

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1294,6 +1294,34 @@ skip_regexp(
12941294
return p;
12951295
}
12961296

1297+
/*
1298+
* Return TRUE if the back reference is legal. We must have seen the close
1299+
* brace.
1300+
* TODO: Should also check that we don't refer to something that is repeated
1301+
* (+*=): what instance of the repetition should we match?
1302+
*/
1303+
static int
1304+
seen_endbrace(int refnum)
1305+
{
1306+
if (!had_endbrace[refnum])
1307+
{
1308+
char_u *p;
1309+
1310+
/* Trick: check if "@<=" or "@<!" follows, in which case
1311+
* the \1 can appear before the referenced match. */
1312+
for (p = regparse; *p != NUL; ++p)
1313+
if (p[0] == '@' && p[1] == '<' && (p[2] == '!' || p[2] == '='))
1314+
break;
1315+
if (*p == NUL)
1316+
{
1317+
EMSG(_("E65: Illegal back reference"));
1318+
rc_did_emsg = TRUE;
1319+
return FALSE;
1320+
}
1321+
}
1322+
return TRUE;
1323+
}
1324+
12971325
static regprog_T *bt_regcomp(char_u *expr, int re_flags);
12981326
static void bt_regfree(regprog_T *prog);
12991327

@@ -2099,24 +2127,8 @@ regatom(int *flagp)
20992127
int refnum;
21002128

21012129
refnum = c - Magic('0');
2102-
/*
2103-
* Check if the back reference is legal. We must have seen the
2104-
* close brace.
2105-
* TODO: Should also check that we don't refer to something
2106-
* that is repeated (+*=): what instance of the repetition
2107-
* should we match?
2108-
*/
2109-
if (!had_endbrace[refnum])
2110-
{
2111-
/* Trick: check if "@<=" or "@<!" follows, in which case
2112-
* the \1 can appear before the referenced match. */
2113-
for (p = regparse; *p != NUL; ++p)
2114-
if (p[0] == '@' && p[1] == '<'
2115-
&& (p[2] == '!' || p[2] == '='))
2116-
break;
2117-
if (*p == NUL)
2118-
EMSG_RET_NULL(_("E65: Illegal back reference"));
2119-
}
2130+
if (!seen_endbrace(refnum))
2131+
return NULL;
21202132
ret = regnode(BACKREF + refnum);
21212133
}
21222134
break;

src/regexp_nfa.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1446,8 +1446,14 @@ nfa_regatom(void)
14461446
case Magic('7'):
14471447
case Magic('8'):
14481448
case Magic('9'):
1449-
EMIT(NFA_BACKREF1 + (no_Magic(c) - '1'));
1450-
nfa_has_backref = TRUE;
1449+
{
1450+
int refnum = no_Magic(c) - '1';
1451+
1452+
if (!seen_endbrace(refnum + 1))
1453+
return FAIL;
1454+
EMIT(NFA_BACKREF1 + refnum);
1455+
nfa_has_backref = TRUE;
1456+
}
14511457
break;
14521458

14531459
case Magic('z'):

src/testdir/test_hlsearch.vim

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,11 @@ func Test_hlsearch_hangs()
3838
return
3939
endif
4040

41-
" This pattern takes forever to match, it should timeout.
41+
" This pattern takes a long time to match, it should timeout.
4242
help
4343
let start = reltime()
4444
set hlsearch nolazyredraw redrawtime=101
45-
let @/ = '\%#=2\v(a|\1)*'
45+
let @/ = '\%#=1a*.*X\@<=b*'
4646
redraw
4747
let elapsed = reltimefloat(reltime(start))
4848
call assert_true(elapsed > 0.1)

src/testdir/test_regexp_latin.vim

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,13 @@ func Test_eow_with_optional()
6262
call assert_equal(expected, actual)
6363
endfor
6464
endfunc
65+
66+
func Test_backref()
67+
new
68+
call setline(1, ['one', 'two', 'three', 'four', 'five'])
69+
call assert_equal(3, search('\%#=1\(e\)\1'))
70+
call assert_equal(3, search('\%#=2\(e\)\1'))
71+
call assert_fails('call search("\\%#=1\\(e\\1\\)")', 'E65:')
72+
call assert_fails('call search("\\%#=2\\(e\\1\\)")', 'E65:')
73+
bwipe!
74+
endfunc

src/testdir/test_statusline.vim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ func Test_statusline()
223223
set statusline=ab%(cd%q%)de
224224
call assert_match('^abde\s*$', s:get_statusline())
225225
copen
226-
call assert_match('^abcd\[Quickfix List\1]de\s*$', s:get_statusline())
226+
call assert_match('^abcd\[Quickfix List]de\s*$', s:get_statusline())
227227
cclose
228228

229229
" %#: Set highlight group. The name must follow and then a # again.

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -764,6 +764,8 @@ static char *(features[]) =
764764

765765
static int included_patches[] =
766766
{ /* Add new patch number below this line */
767+
/**/
768+
645,
767769
/**/
768770
644,
769771
/**/

0 commit comments

Comments
 (0)