From d5ca2dee9d6dd77203f3db7a8fa5da20f4c716de Mon Sep 17 00:00:00 2001 From: "Philip.Hazel" Date: Wed, 22 Mar 2017 15:12:06 +0000 Subject: [PATCH] Fix misbehaving DFA match for possessively repeated character class (Bugzilla 2086). --- ChangeLog | 3 +++ src/pcre2_dfa_match.c | 10 ++++++---- testdata/testinput6 | 3 +++ testdata/testoutput6 | 4 ++++ 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0a504ca..26367c1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -80,6 +80,9 @@ a NULL pattern pointer when Unicode support is available. were longer than 64 code units could cause a buffer overflow. This was a bug in pcre2test. +14. The alternative matching function, pcre2_dfa_match() misbehaved if it +encountered a character class with a possessive repeat, for example [a-f]{3}+. + Version 10.23 14-February-2017 ------------------------------ diff --git a/src/pcre2_dfa_match.c b/src/pcre2_dfa_match.c index 72c6f18..0a952b6 100644 --- a/src/pcre2_dfa_match.c +++ b/src/pcre2_dfa_match.c @@ -544,7 +544,7 @@ for (;;) BOOL partial_newline = FALSE; BOOL could_continue = reset_could_continue; reset_could_continue = FALSE; - + if (ptr > mb->last_used_ptr) mb->last_used_ptr = ptr; /* Make the new state list into the active state list and empty the @@ -597,7 +597,7 @@ for (;;) int state_offset = current_state->offset; int rrc; int count; - + /* A negative offset is a special case meaning "hold off going to this (negated) state until the number of characters in the data field have been skipped". If the could_continue flag was passed over from a previous @@ -633,7 +633,7 @@ for (;;) code = start_code + state_offset; codevalue = *code; - + /* If this opcode inspects a character, but we are at the end of the subject, remember the fact for use when testing for a partial match. */ @@ -2539,11 +2539,13 @@ for (;;) if (isinclass) { int max = (int)GET2(ecode, 1 + IMM2_SIZE); - if (*ecode == OP_CRPOSRANGE) + + if (*ecode == OP_CRPOSRANGE && count >= (int)GET2(ecode, 1)) { active_count--; /* Remove non-match possibility */ next_active_state--; } + if (++count >= max && max != 0) /* Max 0 => no limit */ { ADD_NEW(next_state_offset + 1 + 2 * IMM2_SIZE, 0); } else diff --git a/testdata/testinput6 b/testdata/testinput6 index a7055a8..e928f4d 100644 --- a/testdata/testinput6 +++ b/testdata/testinput6 @@ -4886,4 +4886,7 @@ \= Expect depth limit exceeded a[00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00] +/(02-)?[0-9]{3}-[0-9]{3}/ + 02-123-123 + # End of testinput6 diff --git a/testdata/testoutput6 b/testdata/testoutput6 index edbf1bb..14a5b43 100644 --- a/testdata/testoutput6 +++ b/testdata/testoutput6 @@ -7685,4 +7685,8 @@ No match a[00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00] Failed: error -53: matching depth limit exceeded +/(02-)?[0-9]{3}-[0-9]{3}/ + 02-123-123 + 0: 02-123-123 + # End of testinput6