summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorph10 <ph10@2f5784b3-3f2a-0410-8824-cb99058d5e15>2015-04-08 16:34:24 +0000
committerph10 <ph10@2f5784b3-3f2a-0410-8824-cb99058d5e15>2015-04-08 16:34:24 +0000
commit4a81b0ca19da65ea9a50c208017a74e55c3fd027 (patch)
treea709c6cf7a770cd5a8fc13574fcda12b3b2be127
parentc3579a7581cb8b3ca3c9617d63083afea29de646 (diff)
downloadpcre-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--ChangeLog6
-rw-r--r--pcre_exec.c11
-rw-r--r--testdata/testinput43
-rw-r--r--testdata/testoutput44
4 files changed, 21 insertions, 3 deletions
diff --git a/ChangeLog b/ChangeLog
index 5b723c6..5f07308 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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 --/