diff --git a/RunGrepTest b/RunGrepTest index fa18c41a1..eaed73f7f 100755 --- a/RunGrepTest +++ b/RunGrepTest @@ -927,6 +927,17 @@ echo "RC=$?" >>testtrygrep (cd $srcdir; $valgrind $vjs $pcre2grep -n -B4 -A2 '^(ert|dfg)' ./testdata/grepinput) >>testtrygrep echo "RC=$?" >>testtrygrep +echo "---------------------------- Test 161 -----------------------------" >>testtrygrep +printf 'XfooY\n' >testNinputgrep +$valgrind $vjs $pcre2grep --allow-lookaround-bsk -o '(?=foo\K)' testNinputgrep >>testtrygrep +echo "RC=$?" >>testtrygrep +$valgrind $vjs $pcre2grep --allow-lookaround-bsk --output '$0' '(?=foo\K)' testNinputgrep >>testtrygrep +echo "RC=$?" >>testtrygrep +$valgrind $vjs $pcre2grep --allow-lookaround-bsk --line-offsets '(?=foo\K)' testNinputgrep >>testtrygrep +echo "RC=$?" >>testtrygrep +$valgrind $vjs $pcre2grep --allow-lookaround-bsk --file-offsets '(?=foo\K)' testNinputgrep >>testtrygrep +echo "RC=$?" >>testtrygrep + # Now compare the results. diff --git a/RunGrepTest.bat b/RunGrepTest.bat index 8280534c7..38eeabee5 100644 --- a/RunGrepTest.bat +++ b/RunGrepTest.bat @@ -897,6 +897,17 @@ echo RC=^%ERRORLEVEL%>>testtrygrep (pushd %srcdir% & %pcre2grep% -n -B4 -A2 "^(ert|dfg)" ./testdata/grepinput & popd) >>testtrygrep echo RC=^%ERRORLEVEL%>>testtrygrep +echo ---------------------------- Test 161 ----------------------------->>testtrygrep +%printf% "XfooY\n" >testNinputgrep +%pcre2grep% --allow-lookaround-bsk -o "(?=foo\K)" testNinputgrep >>testtrygrep +echo RC=^%ERRORLEVEL%>>testtrygrep +%pcre2grep% --allow-lookaround-bsk --output "$0" "(?=foo\K)" testNinputgrep >>testtrygrep +echo RC=^%ERRORLEVEL%>>testtrygrep +%pcre2grep% --allow-lookaround-bsk --line-offsets "(?=foo\K)" testNinputgrep >>testtrygrep +echo RC=^%ERRORLEVEL%>>testtrygrep +%pcre2grep% --allow-lookaround-bsk --file-offsets "(?=foo\K)" testNinputgrep >>testtrygrep +echo RC=^%ERRORLEVEL%>>testtrygrep + :: Now compare the results. %cf% %srcdir%\testdata\grepoutput testtrygrep %cfout% diff --git a/src/pcre2grep.c b/src/pcre2grep.c index a5fb0b715..34d8089c1 100644 --- a/src/pcre2grep.c +++ b/src/pcre2grep.c @@ -2208,12 +2208,25 @@ for (; *string != 0; string++) case DDE_CAPTURE: if (value < capture_top) { - PCRE2_SIZE capturesize; + PCRE2_SIZE capturesize, start, end; value *= 2; - capturesize = ovector[value + 1] - ovector[value]; + start = ovector[value]; + end = ovector[value + 1]; + + /* The use of \K may make the end offset earlier than the start. In + this situation, swap them round. */ + + if (start > end) + { + PCRE2_SIZE temp = start; + start = end; + end = temp; + } + + capturesize = end - start; if (capturesize > 0) { - print_match(subject + ovector[value], capturesize); + print_match(subject + start, capturesize); printed = TRUE; } } @@ -2353,7 +2366,12 @@ while (length > 0) if (value < capture_top) { value *= 2; - argslen += ovector[value + 1] - ovector[value]; + + /* The use of \K may make the end offset earlier than the start. */ + + argslen += (ovector[value + 1] > ovector[value])? + ovector[value + 1] - ovector[value] : + ovector[value] - ovector[value + 1]; } argslen--; /* Negate the effect of argslen++ below. */ break; @@ -2419,10 +2437,23 @@ while (length > 0) case DDE_CAPTURE: if (value < capture_top) { - PCRE2_SIZE capturesize; + PCRE2_SIZE capturesize, start, end; value *= 2; - capturesize = ovector[value + 1] - ovector[value]; - memcpy(argsptr, subject + ovector[value], capturesize); + start = ovector[value]; + end = ovector[value + 1]; + + /* The use of \K may make the end offset earlier than the start. In + this situation, swap them round. */ + + if (start > end) + { + PCRE2_SIZE temp = start; + start = end; + end = temp; + } + + capturesize = end - start; + memcpy(argsptr, subject + start, capturesize); argsptr += capturesize; } break; @@ -2847,18 +2878,28 @@ while (ptr < endptr) printname_colon); if (number) fprintf(stdout, "%lu:", linenumber); - /* Handle --line-offsets */ + /* Handle --line-offsets and --file-offsets. The use of \K may make + the end offset earlier than the start. In this situation, swap them + round. */ - if (line_offsets) - fprintf(stdout, "%d,%d" STDOUT_NL, (int)(ptr + offsets[0] - ptr), - (int)(offsets[1] - offsets[0])); + if (line_offsets || file_offsets) + { + PCRE2_SIZE start = offsets[0]; + PCRE2_SIZE end = offsets[1]; - /* Handle --file-offsets */ + if (start > end) + { + PCRE2_SIZE temp = start; + start = end; + end = temp; + } - else if (file_offsets) - fprintf(stdout, "%d,%d" STDOUT_NL, - (int)(filepos + ptr + offsets[0] - ptr), - (int)(offsets[1] - offsets[0])); + if (line_offsets) + fprintf(stdout, "%d,%d" STDOUT_NL, (int)start, (int)(end - start)); + else + fprintf(stdout, "%d,%d" STDOUT_NL, (int)(filepos + start), + (int)(end - start)); + } /* Handle --output (which has already been syntax checked) */ @@ -2881,12 +2922,26 @@ while (ptr < endptr) int n = om->groupnum; if (n == 0 || n < mrc) { - size_t plen = offsets[2*n + 1] - offsets[2*n]; + PCRE2_SIZE start = offsets[2*n]; + PCRE2_SIZE end = offsets[2*n + 1]; + size_t plen; + + /* The use of \K may make the end offset earlier than the start. + In this situation, swap them round. */ + + if (start > end) + { + PCRE2_SIZE temp = start; + start = end; + end = temp; + } + + plen = end - start; if (plen > 0) { if (printed && om_separator != NULL) fprintf(stdout, "%s", om_separator); - print_match(ptr + offsets[n*2], plen); + print_match(ptr + start, plen); printed = TRUE; } } diff --git a/testdata/grepoutput b/testdata/grepoutput index 9d494dd49..3c8b2f48c 100644 --- a/testdata/grepoutput +++ b/testdata/grepoutput @@ -1339,3 +1339,12 @@ RC=0 631-ghj 632-jkl RC=0 +---------------------------- Test 161 ----------------------------- +foo +RC=0 +foo +RC=0 +1:1,3 +RC=0 +1,3 +RC=0