From 5b0c2cbdc2c15d3845dd9cd3799ea0282b65ba94 Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Mon, 2 Oct 2017 16:24:38 +0800 Subject: [PATCH] Regex: Ensure we dont have a thread explosion in ThreadedRegexVM Always remove threads with lower priority that end up on the same instruction as a higher priority thread (as we know they will behave the same from now on) --- src/regex_impl.hh | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/regex_impl.hh b/src/regex_impl.hh index 322b60a4..be61698e 100644 --- a/src/regex_impl.hh +++ b/src/regex_impl.hh @@ -167,7 +167,6 @@ struct ThreadedRegexVM break; } case CompiledRegex::Match: - thread.inst = nullptr; return StepResult::Matched; } } @@ -186,13 +185,16 @@ struct ThreadedRegexVM for (m_pos = Utf8It{m_begin, m_begin, m_end}; m_pos != m_end; ++m_pos) { - for (int i = 0; i < m_threads.size(); ++i) + for (int i = 0; i < m_threads.size(); ) { const auto res = step(i); if (res == StepResult::Matched) { if (match) + { + m_threads.erase(m_threads.begin() + i); continue; // We are not at end, this is not a full match + } m_captures = std::move(m_threads[i].saves); found_match = true; @@ -201,10 +203,19 @@ struct ThreadedRegexVM return true; } else if (res == StepResult::Failed) - m_threads[i].inst = nullptr; + m_threads.erase(m_threads.begin() + i); + else + { + auto it = m_threads.begin() + i; + if (std::find_if(m_threads.begin(), it, [inst = it->inst](auto& t) + { return t.inst == inst; }) != it) + m_threads.erase(it); + else + ++i; + } } - m_threads.erase(std::remove_if(m_threads.begin(), m_threads.end(), - [](const Thread& t) { return t.inst == nullptr; }), m_threads.end()); + // we should never have more than one thread on the same instruction + kak_assert(m_threads.size() <= m_program.bytecode.size()); if (m_threads.empty()) return found_match; } @@ -230,6 +241,7 @@ struct ThreadedRegexVM if (std::find_if(m_threads.begin(), m_threads.end(), [inst](const Thread& t) { return t.inst == inst; }) == m_threads.end()) m_threads.insert(m_threads.begin() + index, {inst, std::move(saves)}); + kak_assert(m_threads.size() < m_program.bytecode.size()); } bool is_line_start() const