diff options
author | ph10 <ph10@2f5784b3-3f2a-0410-8824-cb99058d5e15> | 2015-04-08 16:34:24 +0000 |
---|---|---|
committer | ph10 <ph10@2f5784b3-3f2a-0410-8824-cb99058d5e15> | 2015-04-08 16:34:24 +0000 |
commit | 4a81b0ca19da65ea9a50c208017a74e55c3fd027 (patch) | |
tree | a709c6cf7a770cd5a8fc13574fcda12b3b2be127 | |
parent | c3579a7581cb8b3ca3c9617d63083afea29de646 (diff) | |
download | pcre-4a81b0ca19da65ea9a50c208017a74e55c3fd027.tar.gz |
Fix backtracking bug for \C\X* in UTF mode.
git-svn-id: svn://vcs.exim.org/pcre/code/trunk@1545 2f5784b3-3f2a-0410-8824-cb99058d5e15
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | pcre_exec.c | 11 | ||||
-rw-r--r-- | testdata/testinput4 | 3 | ||||
-rw-r--r-- | testdata/testoutput4 | 4 |
4 files changed, 21 insertions, 3 deletions
@@ -151,6 +151,12 @@ Version 8.37 xx-xxx-2015 37. There was a similar problem to 36 in pcretest for global matches. +38. If a greedy quantified \X was preceded by \C in UTF mode (e.g. \C\X*), + and a subsequent item in the pattern caused a non-match, backtracking over + the repeated \X did not stop, but carried on past the start of the subject, + causing reference to random memory and/or a segfault. This bug was + discovered by the LLVM fuzzer. + Version 8.36 26-September-2014 ------------------------------ diff --git a/pcre_exec.c b/pcre_exec.c index 13dfed5..5fe68b0 100644 --- a/pcre_exec.c +++ b/pcre_exec.c @@ -1376,7 +1376,7 @@ for (;;) break; case OP_DEF: /* DEFINE - always false */ - case OP_FAIL: /* From optimized (?!) condition */ + case OP_FAIL: /* From optimized (?!) condition */ break; /* The condition is an assertion. Call match() to evaluate it - setting @@ -5652,12 +5652,17 @@ for (;;) if (possessive) continue; /* No backtracking */ + /* We use <= pp rather than == pp to detect the start of the run while + backtracking because the use of \C in UTF mode can cause BACKCHAR to + move back past pp. This is just palliative; the use of \C in UTF mode + is fraught with danger. */ + for(;;) { int lgb, rgb; PCRE_PUCHAR fptr; - if (eptr == pp) goto TAIL_RECURSE; /* At start of char run */ + if (eptr <= pp) goto TAIL_RECURSE; /* At start of char run */ RMATCH(eptr, ecode, offset_top, md, eptrb, RM45); if (rrc != MATCH_NOMATCH) RRETURN(rrc); @@ -5675,7 +5680,7 @@ for (;;) for (;;) { - if (eptr == pp) goto TAIL_RECURSE; /* At start of char run */ + if (eptr <= pp) goto TAIL_RECURSE; /* At start of char run */ fptr = eptr - 1; if (!utf) c = *fptr; else { diff --git a/testdata/testinput4 b/testdata/testinput4 index 04fca1a..a0b46f1 100644 --- a/testdata/testinput4 +++ b/testdata/testinput4 @@ -724,4 +724,7 @@ "[\S\V\H]"8 +/\C\X*QT/8 + Ӆ\x0aT + /-- End of testinput4 --/ diff --git a/testdata/testoutput4 b/testdata/testoutput4 index 340a949..386e3b2 100644 --- a/testdata/testoutput4 +++ b/testdata/testoutput4 @@ -1273,4 +1273,8 @@ No match "[\S\V\H]"8 +/\C\X*QT/8 + Ӆ\x0aT +No match + /-- End of testinput4 --/ |