LibRegex: Restore checkpoints when restoring the state post-fork
Fixes the lockup/OOM in #968.
This commit is contained in:
parent
43a07a0fde
commit
cc1f0c3af2
Notes:
github-actions[bot]
2024-10-09 09:21:57 +00:00
Author: https://github.com/alimpfard Commit: https://github.com/LadybirdBrowser/ladybird/commit/cc1f0c3af2c Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/1684
3 changed files with 9 additions and 6 deletions
|
@ -705,6 +705,8 @@ TEST_CASE(ECMA262_match)
|
|||
{ "a$"sv, "a\r\n"sv, true, global_multiline.value() }, // $ should accept all LineTerminators in ECMA262 mode with Multiline.
|
||||
{ "^a"sv, "\ra"sv, true, global_multiline.value() },
|
||||
{ "^(.*?):[ \\t]*([^\\r\\n]*)$"sv, "content-length: 488\r\ncontent-type: application/json; charset=utf-8\r\n"sv, true, global_multiline.value() },
|
||||
{ "^\\?((&?category=[0-9]+)?(&?shippable=1)?(&?ad_type=demand)?(&?page=[0-9]+)?(&?locations=(r|d)_[0-9]+)?)+$"sv,
|
||||
"?category=54&shippable=1&baby_age=p,0,1,3"sv, false }, // ladybird#968, ?+ should not loop forever.
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
|
@ -981,6 +983,7 @@ TEST_CASE(theoretically_infinite_loop)
|
|||
"(a*?)*"sv, // Infinitely matching empty substrings, the outer loop should short-circuit.
|
||||
"(a*)*?"sv, // Should match exactly nothing.
|
||||
"(?:)*?"sv, // Should not generate an infinite fork loop.
|
||||
"(a?)+$"sv, // Infinitely matching empty strings, but with '+' instead of '*'.
|
||||
};
|
||||
for (auto& pattern : patterns) {
|
||||
Regex<ECMA262> re(pattern);
|
||||
|
|
|
@ -1072,20 +1072,20 @@ ALWAYS_INLINE ExecutionResult OpCode_ResetRepeat::execute(MatchInput const&, Mat
|
|||
return ExecutionResult::Continue;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE ExecutionResult OpCode_Checkpoint::execute(MatchInput const& input, MatchState& state) const
|
||||
ALWAYS_INLINE ExecutionResult OpCode_Checkpoint::execute(MatchInput const&, MatchState& state) const
|
||||
{
|
||||
auto id = this->id();
|
||||
if (id >= input.checkpoints.size())
|
||||
input.checkpoints.resize(id + 1);
|
||||
if (id >= state.checkpoints.size())
|
||||
state.checkpoints.resize(id + 1);
|
||||
|
||||
input.checkpoints[id] = state.string_position + 1;
|
||||
state.checkpoints[id] = state.string_position + 1;
|
||||
return ExecutionResult::Continue;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE ExecutionResult OpCode_JumpNonEmpty::execute(MatchInput const& input, MatchState& state) const
|
||||
{
|
||||
u64 current_position = state.string_position;
|
||||
auto checkpoint_position = input.checkpoints[checkpoint()];
|
||||
auto checkpoint_position = state.checkpoints[checkpoint()];
|
||||
|
||||
if (checkpoint_position != 0 && checkpoint_position != current_position + 1) {
|
||||
auto form = this->form();
|
||||
|
|
|
@ -547,7 +547,6 @@ struct MatchInput {
|
|||
mutable Vector<size_t> saved_positions;
|
||||
mutable Vector<size_t> saved_code_unit_positions;
|
||||
mutable Vector<size_t> saved_forks_since_last_save;
|
||||
mutable Vector<u64, 64> checkpoints;
|
||||
mutable Optional<size_t> fork_to_replace;
|
||||
};
|
||||
|
||||
|
@ -562,6 +561,7 @@ struct MatchState {
|
|||
COWVector<Match> matches;
|
||||
COWVector<Vector<Match>> capture_group_matches;
|
||||
COWVector<u64> repetition_marks;
|
||||
Vector<u64, 64> checkpoints;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue