From 544e20a339b5851759f7231433f781beeb0d1783 Mon Sep 17 00:00:00 2001 From: jzmaddock Date: Mon, 23 Oct 2017 18:49:08 +0100 Subject: [PATCH] Regex: Backup and restore internal match_results when saving recursion backtracking info, as well as the state required to restore the recursion stack. Fixes: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=3478#c1 --- include/boost/regex/v4/perl_matcher.hpp | 2 +- .../regex/v4/perl_matcher_non_recursive.hpp | 19 +++++++++++-------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/include/boost/regex/v4/perl_matcher.hpp b/include/boost/regex/v4/perl_matcher.hpp index abd38122..198acc27 100644 --- a/include/boost/regex/v4/perl_matcher.hpp +++ b/include/boost/regex/v4/perl_matcher.hpp @@ -547,7 +547,7 @@ private: void push_repeater_count(int i, repeater_count** s); void push_single_repeat(std::size_t c, const re_repeat* r, BidiIterator last_position, int state_id); void push_non_greedy_repeat(const re_syntax_base* ps); - void push_recursion(int idx, const re_syntax_base* p, results_type* presults); + void push_recursion(int idx, const re_syntax_base* p, results_type* presults, results_type* presults2); void push_recursion_pop(); void push_case_change(bool); diff --git a/include/boost/regex/v4/perl_matcher_non_recursive.hpp b/include/boost/regex/v4/perl_matcher_non_recursive.hpp index fb008f2b..8127ae77 100644 --- a/include/boost/regex/v4/perl_matcher_non_recursive.hpp +++ b/include/boost/regex/v4/perl_matcher_non_recursive.hpp @@ -130,11 +130,11 @@ struct saved_single_repeat : public saved_state template struct saved_recursion : public saved_state { - saved_recursion(int idx, const re_syntax_base* p, Results* pr) - : saved_state(14), recursion_id(idx), preturn_address(p), results(*pr) {} + saved_recursion(int idx, const re_syntax_base* p, Results* pr, Results* pr2) + : saved_state(14), recursion_id(idx), preturn_address(p), internal_results(*pr), prior_results(*pr2) {} int recursion_id; const re_syntax_base* preturn_address; - Results results; + Results internal_results, prior_results; }; struct saved_change_case : public saved_state @@ -354,7 +354,7 @@ inline void perl_matcher::push_single_repeat(st } template -inline void perl_matcher::push_recursion(int idx, const re_syntax_base* p, results_type* presults) +inline void perl_matcher::push_recursion(int idx, const re_syntax_base* p, results_type* presults, results_type* presults2) { saved_recursion* pmp = static_cast*>(m_backup_state); --pmp; @@ -364,7 +364,7 @@ inline void perl_matcher::push_recursion(int id pmp = static_cast*>(m_backup_state); --pmp; } - (void) new (pmp)saved_recursion(idx, p, presults); + (void) new (pmp)saved_recursion(idx, p, presults, presults2); m_backup_state = pmp; } @@ -1052,7 +1052,7 @@ bool perl_matcher::match_endmark() { pstate = recursion_stack.back().preturn_address; *m_presult = recursion_stack.back().results; - push_recursion(recursion_stack.back().idx, recursion_stack.back().preturn_address, &recursion_stack.back().results); + push_recursion(recursion_stack.back().idx, recursion_stack.back().preturn_address, m_presult, &recursion_stack.back().results); recursion_stack.pop_back(); push_repeater_count(-(2 + index), &next_count); } @@ -1075,8 +1075,8 @@ bool perl_matcher::match_match() { BOOST_ASSERT(0 == recursion_stack.back().idx); pstate = recursion_stack.back().preturn_address; + push_recursion(recursion_stack.back().idx, recursion_stack.back().preturn_address, m_presult, &recursion_stack.back().results); *m_presult = recursion_stack.back().results; - push_recursion(recursion_stack.back().idx, recursion_stack.back().preturn_address, &recursion_stack.back().results); recursion_stack.pop_back(); return true; } @@ -1763,8 +1763,9 @@ bool perl_matcher::unwind_recursion(bool r) recursion_stack.push_back(recursion_info()); recursion_stack.back().idx = pmp->recursion_id; recursion_stack.back().preturn_address = pmp->preturn_address; - recursion_stack.back().results = pmp->results; + recursion_stack.back().results = pmp->prior_results; recursion_stack.back().location_of_start = position; + *m_presult = pmp->internal_results; } boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp++); m_backup_state = pmp; @@ -1777,6 +1778,8 @@ bool perl_matcher::unwind_recursion_pop(bool r) saved_state* pmp = static_cast(m_backup_state); if(!r) { + *m_presult = recursion_stack.back().results; + position = recursion_stack.back().location_of_start; recursion_stack.pop_back(); } boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp++);