From 8cada744df6199870356944691fc2c28b627b9d6 Mon Sep 17 00:00:00 2001 From: AnotherTest Date: Sun, 29 Nov 2020 23:44:48 +0330 Subject: [PATCH] LibRegex: Give the bytecode a chance to run when there's no input Fixes #4246 Also adds a test case. --- Libraries/LibRegex/RegexMatcher.cpp | 28 ++++++++++++++++++++++++++++ Libraries/LibRegex/Tests/Regex.cpp | 1 + 2 files changed, 29 insertions(+) diff --git a/Libraries/LibRegex/RegexMatcher.cpp b/Libraries/LibRegex/RegexMatcher.cpp index e6acd97b77..c5d618d7be 100644 --- a/Libraries/LibRegex/RegexMatcher.cpp +++ b/Libraries/LibRegex/RegexMatcher.cpp @@ -27,6 +27,7 @@ #include "RegexMatcher.h" #include "RegexDebug.h" #include "RegexParser.h" +#include #include #include @@ -153,6 +154,33 @@ RegexResult Matcher::match(const Vector views, Optional auto view_length = view.length(); size_t view_index = m_pattern.start_offset; state.string_position = view_index; + + if (view_index == view_length && m_pattern.parser_result.match_length_minimum == 0) { + // Run the code until it tries to consume something. + // This allows non-consuming code to run on empty strings, for instance + // e.g. "Exit" + MatchOutput temp_output { output }; + + input.column = match_count; + input.match_index = match_count; + + state.string_position = view_index; + state.instruction_position = 0; + + auto success = execute(input, state, temp_output, 0); + // This success is acceptable only if it doesn't read anything from the input (input length is 0). + if (state.string_position <= view_index) { + if (success.value()) { + output = move(temp_output); + if (!match_count) { + // Nothing was *actually* matched, so append an empty match. + append_match(input, state, output, view_index); + ++match_count; + } + } + } + } + for (; view_index < view_length; ++view_index) { auto& match_length_minimum = m_pattern.parser_result.match_length_minimum; // FIXME: More performant would be to know the remaining minimum string diff --git a/Libraries/LibRegex/Tests/Regex.cpp b/Libraries/LibRegex/Tests/Regex.cpp index 6ad210d7fb..0e13744ea1 100644 --- a/Libraries/LibRegex/Tests/Regex.cpp +++ b/Libraries/LibRegex/Tests/Regex.cpp @@ -535,6 +535,7 @@ TEST_CASE(ECMA262_match) { "bar.*(?<=foo)", "barbar", false }, { "bar.*(?