Revision: 92
http://www.exim.org/viewvc/pcre2?view=rev&revision=92
Author: ph10
Date: 2014-10-04 16:09:00 +0100 (Sat, 04 Oct 2014)
Log Message:
-----------
Break global loop in pcre2test if matching returns the same substring.
Modified Paths:
--------------
code/trunk/src/pcre2test.c
Modified: code/trunk/src/pcre2test.c
===================================================================
--- code/trunk/src/pcre2test.c 2014-10-03 10:17:18 UTC (rev 91)
+++ code/trunk/src/pcre2test.c 2014-10-04 15:09:00 UTC (rev 92)
@@ -4426,26 +4426,40 @@
PCRE2_JIT_STACK_ASSIGN(compiled_code, jit_callback, NULL);
}
+/* Adjust match_data according to size of offsets required. */
+
+if (dat_datctl.oveccount <= max_oveccount)
+ {
+ SETFLD(match_data, oveccount, dat_datctl.oveccount);
+ }
+else
+ {
+ max_oveccount = dat_datctl.oveccount;
+ PCRE2_MATCH_DATA_FREE(match_data);
+ PCRE2_MATCH_DATA_CREATE(match_data, max_oveccount, NULL);
+ }
+
/* Loop for global matching */
for (gmatched = 0;; gmatched++)
{
int capcount;
+ PCRE2_SIZE *ovector;
+ PCRE2_SIZE ovecsave[2];
+
jit_was_used = FALSE;
+ ovector = FLD(match_data, ovector);
+
+ /* After the first time round a global loop, save the current ovector[0,1] so
+ that we can check that they do change each time. Otherwise a matching bug
+ that returns the same string causes an infinite loop. It has happened! */
- /* Adjust match_data according to size of offsets required. */
-
- if (dat_datctl.oveccount <= max_oveccount)
- {
- SETFLD(match_data, oveccount, dat_datctl.oveccount);
- }
- else
- {
- max_oveccount = dat_datctl.oveccount;
- PCRE2_MATCH_DATA_FREE(match_data);
- PCRE2_MATCH_DATA_CREATE(match_data, max_oveccount, NULL);
- }
-
+ if (gmatched > 0)
+ {
+ ovecsave[0] = ovector[0];
+ ovecsave[1] = ovector[1];
+ }
+
/* Do timing if required. */
if (timeitm > 0)
@@ -4538,7 +4552,7 @@
}
}
- /* The result of the match is in now capcount. First handle a successful
+ /* The result of the match is now in capcount. First handle a successful
match. */
if (capcount >= 0)
@@ -4546,24 +4560,37 @@
int i;
uint8_t *nptr;
BOOL showallused;
- PCRE2_SIZE *ovector;
PCRE2_SIZE leftchar = FLD(match_data, leftchar);
PCRE2_SIZE rightchar = FLD(match_data, rightchar);
/* This is a check against a lunatic return value. */
-
+
if (capcount > (int)dat_datctl.oveccount)
{
fprintf(outfile,
- "** PCRE error: returned count %d is too big for ovector count %d\n",
+ "** PCRE2 error: returned count %d is too big for ovector count %d\n",
capcount, dat_datctl.oveccount);
capcount = dat_datctl.oveccount;
if ((dat_datctl.control & CTL_ANYGLOB) != 0)
{
fprintf(outfile, "** Global loop abandoned\n");
- pat_patctl.options &= ~CTL_ANYGLOB; /* Break g/G loop */
+ dat_datctl.control &= ~CTL_ANYGLOB; /* Break g/G loop */
}
}
+
+ /* If this is not the first time round a global loop, check that the
+ returned string has changed. If not, there is a bug somewhere and we must
+ break the loop because it will go on for ever. We know that for a global
+ match there must be at least two elements in the ovector. This is checked
+ above. */
+
+ if (gmatched > 0 && ovecsave[0] == ovector[0] && ovecsave[1] == ovector[1])
+ {
+ fprintf(outfile,
+ "** PCRE2 error: global repeat returned the same string as previous\n");
+ fprintf(outfile, "** Global loop abandoned\n");
+ dat_datctl.control &= ~CTL_ANYGLOB; /* Break g/G loop */
+ }
/* "allcaptures" requests showing of all captures in the pattern, to check
unset ones at the end. It may be set on the pattern or the data. Implement
@@ -4581,7 +4608,6 @@
/* Output the captured substrings. Note that, for the matched string,
the use of \K in an assertion can make the start later than the end. */
- ovector = FLD(match_data, ovector);
for (i = 0; i < 2*capcount; i += 2)
{
PCRE2_SIZE lleft, lmiddle, lright;