LibRegex: Check inverse_matched after every op, not just at the end

Fixes #13755.

Co-Authored-By: Damien Firmenich <fir.damien@gmail.com>
This commit is contained in:
Ali Mohammad Pur 2022-04-22 02:02:08 +04:30 committed by Linus Groh
parent a79896bb44
commit 1409a48da6
Notes: sideshowbarker 2024-07-17 11:36:18 +09:00
2 changed files with 20 additions and 2 deletions

View file

@ -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);
}

View file

@ -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)