Regex: Fix handling of repeats when mod_x is in effect.

See https://oss-fuzz.com/v2/testcase-detail/6420486177161216?noredirect=1
This commit is contained in:
jzmaddock
2017-10-08 11:52:54 +01:00
parent dc74e145d9
commit f343cab680
2 changed files with 23 additions and 1 deletions

View File

@ -971,7 +971,13 @@ bool basic_regex_parser<charT, traits>::parse_repeat(std::size_t low, std::size_
) )
{ {
// OK we have a perl or emacs regex, check for a '?': // OK we have a perl or emacs regex, check for a '?':
if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_question) if ((this->flags() & (regbase::main_option_type | regbase::mod_x | regbase::no_perl_ex)) == regbase::mod_x)
{
// whitespace skip:
while ((m_position != m_end) && this->m_traits.isctype(*m_position, this->m_mask_space))
++m_position;
}
if((m_position != m_end) && (this->m_traits.syntax_type(*m_position) == regex_constants::syntax_question))
{ {
greedy = false; greedy = false;
++m_position; ++m_position;
@ -1064,6 +1070,12 @@ bool basic_regex_parser<charT, traits>::parse_repeat(std::size_t low, std::size_
// Check for illegal following quantifier, we have to do this here, because // Check for illegal following quantifier, we have to do this here, because
// the extra states we insert below circumvents our usual error checking :-( // the extra states we insert below circumvents our usual error checking :-(
// //
if ((this->flags() & (regbase::main_option_type | regbase::mod_x | regbase::no_perl_ex)) == regbase::mod_x)
{
// whitespace skip:
while ((m_position != m_end) && this->m_traits.isctype(*m_position, this->m_mask_space))
++m_position;
}
switch(this->m_traits.syntax_type(*m_position)) switch(this->m_traits.syntax_type(*m_position))
{ {
case regex_constants::syntax_star: case regex_constants::syntax_star:

View File

@ -486,5 +486,15 @@ void test_pocessive_repeats()
TEST_INVALID_REGEX("\\d*++", perl); TEST_INVALID_REGEX("\\d*++", perl);
TEST_INVALID_REGEX("\\d?++", perl); TEST_INVALID_REGEX("\\d?++", perl);
TEST_INVALID_REGEX("\\d{1,2}++", perl); TEST_INVALID_REGEX("\\d{1,2}++", perl);
TEST_REGEX_SEARCH("(ab +)", perl|mod_x, "abbb", match_default, make_array(0, 4, 0, 4, -2, -2));
TEST_REGEX_SEARCH("(ab +?)", perl | mod_x, "abbb", match_default, make_array(0, 2, 0, 2, -2, -2));
TEST_REGEX_SEARCH("(ab + ?)", perl | mod_x, "abbb", match_default, make_array(0, 2, 0, 2, -2, -2));
TEST_REGEX_SEARCH("(ab ++)", perl | mod_x, "abbb", match_default, make_array(0, 4, 0, 4, -2, -2));
TEST_REGEX_SEARCH("(ab + +)", perl | mod_x, "abbb", match_default, make_array(0, 4, 0, 4, -2, -2));
TEST_INVALID_REGEX("(ab + ++)", perl | mod_x);
TEST_INVALID_REGEX("(ab + + +)", perl | mod_x);
TEST_INVALID_REGEX("(ab + + ?)", perl | mod_x);
} }