mirror of
https://github.com/boostorg/regex.git
synced 2025-07-17 22:32:09 +02:00
Fix recursive expressions where the recursion appears more than once.
Fixes https://github.com/boostorg/regex/issues/87. Also fix some more msvc warnings.
This commit is contained in:
@ -594,7 +594,7 @@ re_syntax_base* basic_regex_creator<charT, traits>::append_set(
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
// everything in range matches:
|
// everything in range matches:
|
||||||
std::memset(result->_map + static_cast<unsigned char>(c1), true, 1 + static_cast<unsigned char>(c2) - static_cast<unsigned char>(c1));
|
std::memset(result->_map + static_cast<unsigned char>(c1), true, static_cast<unsigned char>(1u) + static_cast<unsigned char>(static_cast<unsigned char>(c2) - static_cast<unsigned char>(c1)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
@ -1070,9 +1070,21 @@ int basic_regex_creator<charT, traits>::calculate_backstep(re_syntax_base* state
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct recursion_saver
|
||||||
|
{
|
||||||
|
std::vector<unsigned char> saved_state;
|
||||||
|
std::vector<unsigned char>* state;
|
||||||
|
recursion_saver(std::vector<unsigned char>* p) : saved_state(*p), state(p) {}
|
||||||
|
~recursion_saver()
|
||||||
|
{
|
||||||
|
state->swap(saved_state);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template <class charT, class traits>
|
template <class charT, class traits>
|
||||||
void basic_regex_creator<charT, traits>::create_startmap(re_syntax_base* state, unsigned char* l_map, unsigned int* pnull, unsigned char mask)
|
void basic_regex_creator<charT, traits>::create_startmap(re_syntax_base* state, unsigned char* l_map, unsigned int* pnull, unsigned char mask)
|
||||||
{
|
{
|
||||||
|
recursion_saver saved_recursions(&m_recursion_checks);
|
||||||
int not_last_jump = 1;
|
int not_last_jump = 1;
|
||||||
re_syntax_base* recursion_start = 0;
|
re_syntax_base* recursion_start = 0;
|
||||||
int recursion_sub = 0;
|
int recursion_sub = 0;
|
||||||
|
@ -197,7 +197,7 @@ void basic_regex_parser<charT, traits>::parse(const charT* p1, const charT* p2,
|
|||||||
if(this->m_pdata->m_status)
|
if(this->m_pdata->m_status)
|
||||||
return;
|
return;
|
||||||
// fill in our sub-expression count:
|
// fill in our sub-expression count:
|
||||||
this->m_pdata->m_mark_count = 1 + m_mark_count;
|
this->m_pdata->m_mark_count = 1u + (std::size_t)m_mark_count;
|
||||||
this->finalize(p1, p2);
|
this->finalize(p1, p2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2723,7 +2723,7 @@ option_group_jump:
|
|||||||
{
|
{
|
||||||
#ifndef BOOST_NO_STD_DISTANCE
|
#ifndef BOOST_NO_STD_DISTANCE
|
||||||
if(this->flags() & regbase::save_subexpression_location)
|
if(this->flags() & regbase::save_subexpression_location)
|
||||||
this->m_pdata->m_subs.at(markid - 1).second = std::distance(m_base, m_position) - 1;
|
this->m_pdata->m_subs.at((std::size_t)markid - 1).second = std::distance(m_base, m_position) - 1;
|
||||||
#else
|
#else
|
||||||
if(this->flags() & regbase::save_subexpression_location)
|
if(this->flags() & regbase::save_subexpression_location)
|
||||||
this->m_pdata->m_subs.at(markid - 1).second = (m_position - m_base) - 1;
|
this->m_pdata->m_subs.at(markid - 1).second = (m_position - m_base) - 1;
|
||||||
|
@ -546,7 +546,7 @@ typename w32_regex_traits_implementation<charT>::char_class_type
|
|||||||
if(pos != m_custom_class_names.end())
|
if(pos != m_custom_class_names.end())
|
||||||
return pos->second;
|
return pos->second;
|
||||||
}
|
}
|
||||||
std::size_t state_id = 1 + BOOST_REGEX_DETAIL_NS::get_default_class_id(p1, p2);
|
std::size_t state_id = 1u + (std::size_t)BOOST_REGEX_DETAIL_NS::get_default_class_id(p1, p2);
|
||||||
if(state_id < sizeof(masks) / sizeof(masks[0]))
|
if(state_id < sizeof(masks) / sizeof(masks[0]))
|
||||||
return masks[state_id];
|
return masks[state_id];
|
||||||
return masks[0];
|
return masks[0];
|
||||||
|
@ -157,7 +157,7 @@ c_regex_traits<char>::char_class_type BOOST_REGEX_CALL c_regex_traits<char>::loo
|
|||||||
s[i] = static_cast<char>((std::tolower)(static_cast<unsigned char>(s[i])));
|
s[i] = static_cast<char>((std::tolower)(static_cast<unsigned char>(s[i])));
|
||||||
idx = ::boost::BOOST_REGEX_DETAIL_NS::get_default_class_id(&*s.begin(), &*s.begin() + s.size());
|
idx = ::boost::BOOST_REGEX_DETAIL_NS::get_default_class_id(&*s.begin(), &*s.begin() + s.size());
|
||||||
}
|
}
|
||||||
BOOST_ASSERT(std::size_t(idx+1) < sizeof(masks) / sizeof(masks[0]));
|
BOOST_ASSERT(std::size_t(idx) + 1u < sizeof(masks) / sizeof(masks[0]));
|
||||||
return masks[idx+1];
|
return masks[idx+1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -935,6 +935,7 @@ void test_recursion()
|
|||||||
TEST_REGEX_SEARCH("namespace\\s+(\\w+)\\s+(\\{(?:[^{}]*(?:(?2)[^{}]*)*)?\\})", perl, "namespace one { namespace two { int foo(){} } { {{{ } } } } {}}", match_default, make_array(0, 64, 10, 13, 14, 64, -2, -2));
|
TEST_REGEX_SEARCH("namespace\\s+(\\w+)\\s+(\\{(?:[^{}]*(?:(?2)[^{}]*)*)?\\})", perl, "namespace one { namespace two { int foo(){} } { {{{ } } } } {}}", match_default, make_array(0, 64, 10, 13, 14, 64, -2, -2));
|
||||||
TEST_INVALID_REGEX("((?1)|a)", perl);
|
TEST_INVALID_REGEX("((?1)|a)", perl);
|
||||||
TEST_REGEX_SEARCH("a(?0)?", perl, "aaaaa", match_default, make_array(0, 5, -2, -2));
|
TEST_REGEX_SEARCH("a(?0)?", perl, "aaaaa", match_default, make_array(0, 5, -2, -2));
|
||||||
|
TEST_REGEX_SEARCH("((?(DEFINE)(?'a'A)(?'b'(?&a)?(?&a)))(?&b)?)", perl, "AA", match_default, make_array(0, 2, 0, 2, -1, -1, -2, 2, 2, 2, 2, -1, -1, -2, -2));
|
||||||
|
|
||||||
// Recursion to a named sub with a name that is used multiple times:
|
// Recursion to a named sub with a name that is used multiple times:
|
||||||
TEST_REGEX_SEARCH("(?:(?<A>a+)|(?<A>b+))\\.(?&A)", perl, "aaaa.aa", match_default, make_array(0, 7, 0, 4, -1, -1, -2, -2));
|
TEST_REGEX_SEARCH("(?:(?<A>a+)|(?<A>b+))\\.(?&A)", perl, "aaaa.aa", match_default, make_array(0, 7, 0, 4, -1, -1, -2, -2));
|
||||||
|
Reference in New Issue
Block a user