Skip to content

Commit 50453e3

Browse files
committed
Regex: Repeating a repeat is not allowed, even if there is a comment block in between the two.
Fixes: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=3479#c2
1 parent 544e20a commit 50453e3

File tree

2 files changed

+39
-15
lines changed

2 files changed

+39
-15
lines changed

include/boost/regex/v4/basic_regex_parser.hpp

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1077,21 +1077,40 @@ bool basic_regex_parser<charT, traits>::parse_repeat(std::size_t low, std::size_
10771077
// Check for illegal following quantifier, we have to do this here, because
10781078
// the extra states we insert below circumvents our usual error checking :-(
10791079
//
1080-
if ((this->flags() & (regbase::main_option_type | regbase::mod_x | regbase::no_perl_ex)) == regbase::mod_x)
1080+
bool contin = false;
1081+
do
10811082
{
1082-
// whitespace skip:
1083-
while ((m_position != m_end) && this->m_traits.isctype(*m_position, this->m_mask_space))
1084-
++m_position;
1085-
}
1086-
switch(this->m_traits.syntax_type(*m_position))
1087-
{
1088-
case regex_constants::syntax_star:
1089-
case regex_constants::syntax_plus:
1090-
case regex_constants::syntax_question:
1091-
case regex_constants::syntax_open_brace:
1092-
fail(regex_constants::error_badrepeat, m_position - m_base);
1093-
return false;
1094-
}
1083+
if ((this->flags() & (regbase::main_option_type | regbase::mod_x | regbase::no_perl_ex)) == regbase::mod_x)
1084+
{
1085+
// whitespace skip:
1086+
while ((m_position != m_end) && this->m_traits.isctype(*m_position, this->m_mask_space))
1087+
++m_position;
1088+
}
1089+
if (m_position != m_end)
1090+
{
1091+
switch (this->m_traits.syntax_type(*m_position))
1092+
{
1093+
case regex_constants::syntax_star:
1094+
case regex_constants::syntax_plus:
1095+
case regex_constants::syntax_question:
1096+
case regex_constants::syntax_open_brace:
1097+
fail(regex_constants::error_badrepeat, m_position - m_base);
1098+
return false;
1099+
case regex_constants::syntax_open_mark:
1100+
// Do we have a comment? If so we need to skip it here...
1101+
if ((m_position + 2 < m_end) && this->m_traits.syntax_type(*(m_position + 1)) == regex_constants::syntax_question
1102+
&& this->m_traits.syntax_type(*(m_position + 2)) == regex_constants::syntax_hash)
1103+
{
1104+
while ((m_position != m_end)
1105+
&& (this->m_traits.syntax_type(*m_position++) != regex_constants::syntax_close_mark)) {
1106+
}
1107+
}
1108+
contin = true;
1109+
}
1110+
}
1111+
else
1112+
contin = false;
1113+
} while (contin);
10951114
}
10961115
re_brace* pb = static_cast<re_brace*>(this->insert_state(insert_point, syntax_element_startmark, sizeof(re_brace)));
10971116
pb->index = -3;
@@ -2010,7 +2029,7 @@ bool basic_regex_parser<charT, traits>::parse_perl_extension()
20102029
{
20112030
while((m_position != m_end)
20122031
&& (this->m_traits.syntax_type(*m_position++) != regex_constants::syntax_close_mark))
2013-
{}
2032+
{}
20142033
return true;
20152034
}
20162035
//

test/regress/test_perl_ex.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,11 @@ void test_options()
205205
TEST_REGEX_SEARCH("(a (?x)b c)d e", perl, "a bcde", match_default, make_array(-2, -2));
206206
TEST_REGEX_SEARCH("(a b(?x)c d (?-x)e f)", perl, "a bcde f", match_default, make_array(0, 8, 0, 8, -2, -2));
207207
TEST_REGEX_SEARCH("(a b(?x)c d (?-x)e f)", perl, "abcdef", match_default, make_array(-2, -2));
208+
209+
TEST_INVALID_REGEX("a++(?#abc)+", perl);
210+
TEST_INVALID_REGEX("a++(?#abc)?", perl);
211+
TEST_INVALID_REGEX("a++(?#abc)*", perl);
212+
TEST_INVALID_REGEX("a++(?#abc){2}", perl);
208213
}
209214

210215
void test_options2()

0 commit comments

Comments
 (0)