forked from boostorg/regex
Allow back references to refer to a capture that hasn't happened yet ("forward reference").
Fixes https://github.com/boostorg/regex/issues/133.
This commit is contained in:
@ -98,6 +98,7 @@ private:
|
||||
std::ptrdiff_t m_alt_insert_point; // where to insert the next alternative
|
||||
bool m_has_case_change; // true if somewhere in the current block the case has changed
|
||||
unsigned m_recursion_count; // How many times we've called parse_all.
|
||||
unsigned m_max_backref; // Largest index of any backref.
|
||||
#if defined(BOOST_REGEX_MSVC) && defined(_M_IX86)
|
||||
// This is an ugly warning suppression workaround (for warnings *inside* std::vector
|
||||
// that can not otherwise be suppressed)...
|
||||
@ -114,7 +115,7 @@ private:
|
||||
template <class charT, class traits>
|
||||
basic_regex_parser<charT, traits>::basic_regex_parser(regex_data<charT, traits>* data)
|
||||
: basic_regex_creator<charT, traits>(data), m_parser_proc(), m_base(0), m_end(0), m_position(0),
|
||||
m_mark_count(0), m_mark_reset(-1), m_max_mark(0), m_paren_start(0), m_alt_insert_point(0), m_has_case_change(false), m_recursion_count(0)
|
||||
m_mark_count(0), m_mark_reset(-1), m_max_mark(0), m_paren_start(0), m_alt_insert_point(0), m_has_case_change(false), m_recursion_count(0), m_max_backref(0)
|
||||
{
|
||||
}
|
||||
|
||||
@ -184,6 +185,13 @@ void basic_regex_parser<charT, traits>::parse(const charT* p1, const charT* p2,
|
||||
return;
|
||||
// fill in our sub-expression count:
|
||||
this->m_pdata->m_mark_count = 1u + (std::size_t)m_mark_count;
|
||||
//
|
||||
// Check we don't have backreferences to sub-expressions which don't exist:
|
||||
//
|
||||
if (m_max_backref > m_mark_count)
|
||||
{
|
||||
fail(regex_constants::error_backref, std::distance(m_base, m_position), "Found a backreference to a non-existant sub-expression.");
|
||||
}
|
||||
this->finalize(p1, p2);
|
||||
}
|
||||
|
||||
@ -529,11 +537,6 @@ bool basic_regex_parser<charT, traits>::parse_open_paren()
|
||||
// restore the alternate insertion point:
|
||||
//
|
||||
this->m_alt_insert_point = last_alt_point;
|
||||
//
|
||||
// allow backrefs to this mark:
|
||||
//
|
||||
if(markid > 0)
|
||||
this->m_backrefs.set(markid);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -899,12 +902,14 @@ escape_type_class_jump:
|
||||
}
|
||||
if(negative)
|
||||
i = 1 + (static_cast<std::intmax_t>(m_mark_count) - i);
|
||||
if(((i < hash_value_mask) && (i > 0) && (this->m_backrefs.test((std::size_t)i))) || ((i >= hash_value_mask) && (this->m_pdata->get_id((int)i) > 0) && (this->m_backrefs.test(this->m_pdata->get_id((int)i)))))
|
||||
if(((i < hash_value_mask) && (i > 0)) || ((i >= hash_value_mask) && (this->m_pdata->get_id((int)i) > 0)))
|
||||
{
|
||||
m_position = pc;
|
||||
re_brace* pb = static_cast<re_brace*>(this->append_state(syntax_element_backref, sizeof(re_brace)));
|
||||
pb->index = (int)i;
|
||||
pb->icase = this->flags() & regbase::icase;
|
||||
if ((i > m_max_backref) && (i < hash_value_mask))
|
||||
m_max_backref = i;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1934,12 +1939,14 @@ bool basic_regex_parser<charT, traits>::parse_backref()
|
||||
charT c = unescape_character();
|
||||
this->append_literal(c);
|
||||
}
|
||||
else if((i > 0) && (this->m_backrefs.test((std::size_t)i)))
|
||||
else if((i > 0))
|
||||
{
|
||||
m_position = pc;
|
||||
re_brace* pb = static_cast<re_brace*>(this->append_state(syntax_element_backref, sizeof(re_brace)));
|
||||
pb->index = (int)i;
|
||||
pb->icase = this->flags() & regbase::icase;
|
||||
if(i > m_max_backref)
|
||||
m_max_backref = i;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -2695,10 +2702,6 @@ option_group_jump:
|
||||
{
|
||||
if(this->flags() & regbase::save_subexpression_location)
|
||||
this->m_pdata->m_subs.at((std::size_t)markid - 1).second = std::distance(m_base, m_position) - 1;
|
||||
//
|
||||
// allow backrefs to this mark:
|
||||
//
|
||||
this->m_backrefs.set(markid);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
Reference in New Issue
Block a user