diff options
-rw-r--r-- | Tests/LibRegex/Regex.cpp | 11 | ||||
-rw-r--r-- | Userland/Libraries/LibRegex/RegexByteCode.cpp | 11 |
2 files changed, 20 insertions, 2 deletions
diff --git a/Tests/LibRegex/Regex.cpp b/Tests/LibRegex/Regex.cpp index 50420c504a..41c7d1c355 100644 --- a/Tests/LibRegex/Regex.cpp +++ b/Tests/LibRegex/Regex.cpp @@ -1034,3 +1034,14 @@ TEST_CASE(single_match_flag) EXPECT_EQ(result.matches.first().view.to_string(), "A"sv); } } + +TEST_CASE(inversion_state_in_char_class) +{ + // #13755, /[\S\s]/.exec("hello") should be [ "h" ], not null. + Regex<ECMA262> re("[\\S\\s]", ECMAScriptFlags::Global | (ECMAScriptFlags)regex::AllFlags::SingleMatch); + + auto result = re.match("hello"); + EXPECT_EQ(result.success, true); + EXPECT_EQ(result.matches.size(), 1u); + EXPECT_EQ(result.matches.first().view.to_string(), "h"sv); +} diff --git a/Userland/Libraries/LibRegex/RegexByteCode.cpp b/Userland/Libraries/LibRegex/RegexByteCode.cpp index 4a1021ff77..c1dd64f2b3 100644 --- a/Userland/Libraries/LibRegex/RegexByteCode.cpp +++ b/Userland/Libraries/LibRegex/RegexByteCode.cpp @@ -458,16 +458,18 @@ ALWAYS_INLINE ExecutionResult OpCode_Compare::execute(MatchInput const& input, M auto compare_type = (CharacterCompareType)m_bytecode->at(offset++); - if (compare_type == CharacterCompareType::Inverse) + if (compare_type == CharacterCompareType::Inverse) { inverse = true; + continue; - else if (compare_type == CharacterCompareType::TemporaryInverse) { + } else if (compare_type == CharacterCompareType::TemporaryInverse) { // If "TemporaryInverse" is given, negate the current inversion state only for the next opcode. // it follows that this cannot be the last compare element. VERIFY(i != arguments_count() - 1); temporary_inverse = true; reset_temp_inverse = false; + continue; } else if (compare_type == CharacterCompareType::Char) { u32 ch = m_bytecode->at(offset++); @@ -598,6 +600,11 @@ ALWAYS_INLINE ExecutionResult OpCode_Compare::execute(MatchInput const& input, M VERIFY_NOT_REACHED(); break; } + + if (current_inversion_state() && !inverse_matched) { + advance_string_position(state, input.view); + inverse_matched = true; + } } if (current_inversion_state() && !inverse_matched) |