mirror of
https://github.com/vim/vim.git
synced 2025-07-25 10:54:51 -04:00
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)
This commit is contained in:
parent
5b1affefd0
commit
1ef9bbe215
48
src/regexp.c
48
src/regexp.c
@ -1294,6 +1294,34 @@ skip_regexp(
|
|||||||
return p;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
static regprog_T *bt_regcomp(char_u *expr, int re_flags);
|
static regprog_T *bt_regcomp(char_u *expr, int re_flags);
|
||||||
static void bt_regfree(regprog_T *prog);
|
static void bt_regfree(regprog_T *prog);
|
||||||
|
|
||||||
@ -2099,24 +2127,8 @@ regatom(int *flagp)
|
|||||||
int refnum;
|
int refnum;
|
||||||
|
|
||||||
refnum = c - Magic('0');
|
refnum = c - Magic('0');
|
||||||
/*
|
if (!seen_endbrace(refnum))
|
||||||
* Check if the back reference is legal. We must have seen the
|
return NULL;
|
||||||
* 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"));
|
|
||||||
}
|
|
||||||
ret = regnode(BACKREF + refnum);
|
ret = regnode(BACKREF + refnum);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1446,8 +1446,14 @@ nfa_regatom(void)
|
|||||||
case Magic('7'):
|
case Magic('7'):
|
||||||
case Magic('8'):
|
case Magic('8'):
|
||||||
case Magic('9'):
|
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;
|
break;
|
||||||
|
|
||||||
case Magic('z'):
|
case Magic('z'):
|
||||||
|
@ -38,11 +38,11 @@ func Test_hlsearch_hangs()
|
|||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
|
||||||
" This pattern takes forever to match, it should timeout.
|
" This pattern takes a long time to match, it should timeout.
|
||||||
help
|
help
|
||||||
let start = reltime()
|
let start = reltime()
|
||||||
set hlsearch nolazyredraw redrawtime=101
|
set hlsearch nolazyredraw redrawtime=101
|
||||||
let @/ = '\%#=2\v(a|\1)*'
|
let @/ = '\%#=1a*.*X\@<=b*'
|
||||||
redraw
|
redraw
|
||||||
let elapsed = reltimefloat(reltime(start))
|
let elapsed = reltimefloat(reltime(start))
|
||||||
call assert_true(elapsed > 0.1)
|
call assert_true(elapsed > 0.1)
|
||||||
|
@ -62,3 +62,13 @@ func Test_eow_with_optional()
|
|||||||
call assert_equal(expected, actual)
|
call assert_equal(expected, actual)
|
||||||
endfor
|
endfor
|
||||||
endfunc
|
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
|
||||||
|
@ -223,7 +223,7 @@ func Test_statusline()
|
|||||||
set statusline=ab%(cd%q%)de
|
set statusline=ab%(cd%q%)de
|
||||||
call assert_match('^abde\s*$', s:get_statusline())
|
call assert_match('^abde\s*$', s:get_statusline())
|
||||||
copen
|
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
|
cclose
|
||||||
|
|
||||||
" %#: Set highlight group. The name must follow and then a # again.
|
" %#: Set highlight group. The name must follow and then a # again.
|
||||||
|
@ -764,6 +764,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
645,
|
||||||
/**/
|
/**/
|
||||||
644,
|
644,
|
||||||
/**/
|
/**/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user