diff --git a/src/nvim/regexp.c b/src/nvim/regexp.c index 8529bcb49a..4abde83bba 100644 --- a/src/nvim/regexp.c +++ b/src/nvim/regexp.c @@ -15525,7 +15525,30 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, regsubs_T *subm } } } else { - if (addstate(nextlist, start, m, NULL, clen) == NULL) { + uint8_t *save_line = rex.line; + uint8_t *save_input = rex.input; + linenr_T save_lnum = rex.lnum; + + // At the end of a line the match can only start on the next + // line, use that position instead of the line break. + if (REG_MULTI && clen == 0 && nfa_endp != NULL + && rex.lnum < nfa_endp->se_u.pos.lnum) { + char *next_line = reg_getline(rex.lnum + 1); + + if (next_line != NULL) { + rex.line = (uint8_t *)next_line; + rex.input = rex.line; + rex.lnum++; + } + } + + r = addstate(nextlist, start, m, NULL, clen); + + rex.line = save_line; + rex.input = save_input; + rex.lnum = save_lnum; + + if (r == NULL) { nfa_match = NFA_TOO_EXPENSIVE; goto theend; } diff --git a/test/old/testdir/test_regexp_utf8.vim b/test/old/testdir/test_regexp_utf8.vim index d6284a559f..f5ec0b77d2 100644 --- a/test/old/testdir/test_regexp_utf8.vim +++ b/test/old/testdir/test_regexp_utf8.vim @@ -656,4 +656,29 @@ func Test_regex_collection_range_with_composing_crash() bwipe! endfunc +" A submatch in a look-behind must not start on the previous line. See +" issue #20802. +func Test_lookbehind_submatch_on_second_line() + new + for re in range(0, 2) + exe "set re=" .. re + call setline(1, ['testing', 'testing']) + %s/\v(.)@<=/[\1]/g + call assert_equal(['t[t]e[e]s[s]t[t]i[i]n[n]g', + \ 't[t]e[e]s[s]t[t]i[i]n[n]g'], getline(1, '$'), 're=' .. re) + %d _ + + " With "\_." the look-behind can match the line break, then the submatch + " does start on the previous line. + call setline(1, ['abc', 'def']) + %s/\v(\_.)@<=/[\1]/g + call assert_equal(['a[a]b[b]c[c]', '[]d[d]e[e]f[f]'], + \ getline(1, '$'), 're=' .. re) + %d _ + endfor + + set re& + bwipe! +endfunc + " vim: shiftwidth=2 sts=2 expandtab