Skip to content

Commit 30f4c35

Browse files
committed
updated for version 7.4.036
Problem: NFA engine does not capture group correctly when using \@>. (ZyX) Solution: Copy submatches before doing the recursive match.
1 parent 1d8eccc commit 30f4c35

File tree

4 files changed

+33
-17
lines changed

4 files changed

+33
-17
lines changed

src/regexp_nfa.c

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ enum
3636
{
3737
NFA_SPLIT = -1024,
3838
NFA_MATCH,
39-
NFA_SKIP_CHAR, /* matches a 0-length char */
39+
NFA_EMPTY, /* matches 0-length */
4040

4141
NFA_START_COLL, /* [abc] start */
4242
NFA_END_COLL, /* [abc] end */
@@ -2005,8 +2005,8 @@ nfa_regpiece()
20052005
{
20062006
/* Ignore result of previous call to nfa_regatom() */
20072007
post_ptr = post_start + my_post_start;
2008-
/* NFA_SKIP_CHAR has 0-length and works everywhere */
2009-
EMIT(NFA_SKIP_CHAR);
2008+
/* NFA_EMPTY is 0-length and works everywhere */
2009+
EMIT(NFA_EMPTY);
20102010
return OK;
20112011
}
20122012

@@ -2170,16 +2170,16 @@ nfa_regbranch()
21702170
old_post_pos = (int)(post_ptr - post_start);
21712171
if (nfa_regconcat() == FAIL)
21722172
return FAIL;
2173-
/* if concat is empty, skip a input char. But do emit a node */
2173+
/* if concat is empty do emit a node */
21742174
if (old_post_pos == (int)(post_ptr - post_start))
2175-
EMIT(NFA_SKIP_CHAR);
2175+
EMIT(NFA_EMPTY);
21762176
EMIT(NFA_CONCAT);
21772177
ch = peekchr();
21782178
}
21792179

2180-
/* Even if a branch is empty, emit one node for it */
2180+
/* if a branch is empty, emit one node for it */
21812181
if (old_post_pos == (int)(post_ptr - post_start))
2182-
EMIT(NFA_SKIP_CHAR);
2182+
EMIT(NFA_EMPTY);
21832183

21842184
return OK;
21852185
}
@@ -2423,7 +2423,7 @@ nfa_set_code(c)
24232423
case NFA_STAR_NONGREEDY: STRCPY(code, "NFA_STAR_NONGREEDY "); break;
24242424
case NFA_QUEST: STRCPY(code, "NFA_QUEST"); break;
24252425
case NFA_QUEST_NONGREEDY: STRCPY(code, "NFA_QUEST_NON_GREEDY"); break;
2426-
case NFA_SKIP_CHAR: STRCPY(code, "NFA_SKIP_CHAR"); break;
2426+
case NFA_EMPTY: STRCPY(code, "NFA_EMPTY"); break;
24272427
case NFA_OR: STRCPY(code, "NFA_OR"); break;
24282428

24292429
case NFA_START_COLL: STRCPY(code, "NFA_START_COLL"); break;
@@ -3067,7 +3067,7 @@ nfa_max_width(startstate, depth)
30673067
case NFA_ZSTART:
30683068
case NFA_ZEND:
30693069
case NFA_OPT_CHARS:
3070-
case NFA_SKIP_CHAR:
3070+
case NFA_EMPTY:
30713071
case NFA_START_PATTERN:
30723072
case NFA_END_PATTERN:
30733073
case NFA_COMPOSING:
@@ -3265,15 +3265,14 @@ post2nfa(postfix, end, nfa_calc_size)
32653265
PUSH(frag(e1.start, e2.out));
32663266
break;
32673267

3268-
case NFA_SKIP_CHAR:
3269-
/* Symbol of 0-length, Used in a repetition
3270-
* with max/min count of 0 */
3268+
case NFA_EMPTY:
3269+
/* 0-length, used in a repetition with max/min count of 0 */
32713270
if (nfa_calc_size == TRUE)
32723271
{
32733272
nstate++;
32743273
break;
32753274
}
3276-
s = alloc_state(NFA_SKIP_CHAR, NULL, NULL);
3275+
s = alloc_state(NFA_EMPTY, NULL, NULL);
32773276
if (s == NULL)
32783277
goto theend;
32793278
PUSH(frag(s, list1(&s->out)));
@@ -4209,7 +4208,7 @@ addstate(l, state, subs_arg, pim, off)
42094208
case NFA_MOPEN:
42104209
case NFA_ZEND:
42114210
case NFA_SPLIT:
4212-
case NFA_SKIP_CHAR:
4211+
case NFA_EMPTY:
42134212
/* These nodes are not added themselves but their "out" and/or
42144213
* "out1" may be added below. */
42154214
break;
@@ -4337,7 +4336,7 @@ addstate(l, state, subs_arg, pim, off)
43374336
subs = addstate(l, state->out1, subs, pim, off);
43384337
break;
43394338

4340-
case NFA_SKIP_CHAR:
4339+
case NFA_EMPTY:
43414340
case NFA_NOPEN:
43424341
case NFA_NCLOSE:
43434342
subs = addstate(l, state->out, subs, pim, off);
@@ -5604,9 +5603,13 @@ nfa_regmatch(prog, start, submatch, m)
56045603
{
56055604
int in_use = m->norm.in_use;
56065605

5607-
/* Copy submatch info for the recursive call, so that
5608-
* \1 can be matched. */
5606+
/* Copy submatch info for the recursive call, opposite
5607+
* of what happens on success below. */
56095608
copy_sub_off(&m->norm, &t->subs.norm);
5609+
#ifdef FEAT_SYN_HL
5610+
if (nfa_has_zsubexpr)
5611+
copy_sub_off(&m->synt, &t->subs.synt);
5612+
#endif
56105613

56115614
/*
56125615
* First try matching the invisible match, then what
@@ -5713,6 +5716,13 @@ nfa_regmatch(prog, start, submatch, m)
57135716
#endif
57145717
break;
57155718
}
5719+
/* Copy submatch info to the recursive call, opposite of what
5720+
* happens afterwards. */
5721+
copy_sub_off(&m->norm, &t->subs.norm);
5722+
#ifdef FEAT_SYN_HL
5723+
if (nfa_has_zsubexpr)
5724+
copy_sub_off(&m->synt, &t->subs.synt);
5725+
#endif
57165726

57175727
/* First try matching the pattern. */
57185728
result = recursive_regmatch(t->state, NULL, prog,

src/testdir/test64.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,7 @@ STARTTEST
430430
:call add(tl, [2, '\(a*\)\@>a', 'aaaa'])
431431
:call add(tl, [2, '\(a*\)\@>b', 'aaab', 'aaab', 'aaa'])
432432
:call add(tl, [2, '^\(.\{-}b\)\@>.', ' abcbd', ' abc', ' ab'])
433+
:call add(tl, [2, '\(.\{-}\)\(\)\@>$', 'abc', 'abc', 'abc', ''])
433434
:" TODO: BT engine does not restore submatch after failure
434435
:call add(tl, [1, '\(a*\)\@>a\|a\+', 'aaaa', 'aaaa'])
435436
:"

src/testdir/test64.ok

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -992,6 +992,9 @@ OK 2 - \(a*\)\@>b
992992
OK 0 - ^\(.\{-}b\)\@>.
993993
OK 1 - ^\(.\{-}b\)\@>.
994994
OK 2 - ^\(.\{-}b\)\@>.
995+
OK 0 - \(.\{-}\)\(\)\@>$
996+
OK 1 - \(.\{-}\)\(\)\@>$
997+
OK 2 - \(.\{-}\)\(\)\@>$
995998
OK 0 - \(a*\)\@>a\|a\+
996999
OK 2 - \(a*\)\@>a\|a\+
9971000
OK 0 - \_[^8-9]\+

src/version.c

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

739739
static int included_patches[] =
740740
{ /* Add new patch number below this line */
741+
/**/
742+
36,
741743
/**/
742744
35,
743745
/**/

0 commit comments

Comments
 (0)