diff --git a/Libraries/LibRegex/RegexByteCode.cpp b/Libraries/LibRegex/RegexByteCode.cpp index a8ae99b735b..d95cb1be283 100644 --- a/Libraries/LibRegex/RegexByteCode.cpp +++ b/Libraries/LibRegex/RegexByteCode.cpp @@ -585,6 +585,9 @@ ALWAYS_INLINE ExecutionResult OpCode_Compare::execute(MatchInput const& input, M } case CharacterCompareType::Reference: { auto reference_number = (size_t)m_bytecode->at(offset++); + if (input.match_index >= state.capture_group_matches.size()) + return ExecutionResult::Failed_ExecuteLowPrioForks; + auto& groups = state.capture_group_matches.at(input.match_index); if (groups.size() <= reference_number) return ExecutionResult::Failed_ExecuteLowPrioForks; diff --git a/Tests/LibRegex/Regex.cpp b/Tests/LibRegex/Regex.cpp index adf8456959d..e4a94e916f2 100644 --- a/Tests/LibRegex/Regex.cpp +++ b/Tests/LibRegex/Regex.cpp @@ -741,6 +741,8 @@ TEST_CASE(ECMA262_match) // Tests nested lookahead with alternation - verifies proper save/restore stack cleanup { "a(?=.(?=c)|b)b"sv, "ab"sv, true }, { "(?=)(?=\\d)"sv, "smart"sv, false }, + // Backrefs are cleared after lookaheads, the indices should be checked before lookup. + { "(?!(b))\\1"sv, "a"sv, false }, }; for (auto& test : tests) {