mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 09:17:35 +00:00
LibRegex: Implement min/max repetition using the Repeat bytecode
This makes repetitions with large max bounds work correctly. Also fixes an OOM issue found by OSS-Fuzz: https://oss-fuzz.com/testcase?key=4725721980338176
This commit is contained in:
parent
b64d6bb3a3
commit
98624fe03f
1 changed files with 23 additions and 6 deletions
|
@ -339,17 +339,34 @@ public:
|
||||||
new_bytecode.insert_bytecode_repetition_n(bytecode_to_repeat, minimum, repetition_mark_id);
|
new_bytecode.insert_bytecode_repetition_n(bytecode_to_repeat, minimum, repetition_mark_id);
|
||||||
|
|
||||||
if (maximum.has_value()) {
|
if (maximum.has_value()) {
|
||||||
|
// (REPEAT REGEXP MIN)
|
||||||
|
// LABEL _MAX_LOOP |
|
||||||
|
// FORK END |
|
||||||
|
// REGEXP |
|
||||||
|
// REPEAT _MAX_LOOP MAX-1 | if max > min
|
||||||
|
// REGEXP |
|
||||||
|
// FORK END |
|
||||||
|
// LABEL END |
|
||||||
auto jump_kind = static_cast<ByteCodeValueType>(greedy ? OpCodeId::ForkStay : OpCodeId::ForkJump);
|
auto jump_kind = static_cast<ByteCodeValueType>(greedy ? OpCodeId::ForkStay : OpCodeId::ForkJump);
|
||||||
if (maximum.value() > minimum) {
|
if (maximum.value() > minimum) {
|
||||||
auto diff = maximum.value() - minimum;
|
|
||||||
new_bytecode.empend(jump_kind);
|
new_bytecode.empend(jump_kind);
|
||||||
new_bytecode.empend(diff * (bytecode_to_repeat.size() + 2)); // Jump to the _END label
|
new_bytecode.empend((ByteCodeValueType)0); // Placeholder for the jump target.
|
||||||
|
auto pre_loop_fork_jump_index = new_bytecode.size();
|
||||||
for (T i = 0; i < diff; ++i) {
|
auto repetitions = maximum.value() - minimum;
|
||||||
|
dbgln("max {}, min {}, reps {}", *maximum, minimum, repetitions);
|
||||||
|
if (repetitions > 1) {
|
||||||
new_bytecode.extend(bytecode_to_repeat);
|
new_bytecode.extend(bytecode_to_repeat);
|
||||||
new_bytecode.empend(jump_kind);
|
new_bytecode.empend((ByteCodeValueType)OpCodeId::Repeat);
|
||||||
new_bytecode.empend((diff - i - 1) * (bytecode_to_repeat.size() + 2)); // Jump to the _END label
|
new_bytecode.empend(bytecode_to_repeat.size() + 2);
|
||||||
|
new_bytecode.empend(static_cast<ByteCodeValueType>(repetitions - 1));
|
||||||
|
new_bytecode.empend(repetition_mark_id);
|
||||||
}
|
}
|
||||||
|
new_bytecode.extend(bytecode_to_repeat);
|
||||||
|
new_bytecode.empend(jump_kind);
|
||||||
|
new_bytecode.empend((ByteCodeValueType)0); // Placeholder for the jump target.
|
||||||
|
auto post_loop_fork_jump_index = new_bytecode.size();
|
||||||
|
new_bytecode[pre_loop_fork_jump_index - 1] = (ByteCodeValueType)(new_bytecode.size() - pre_loop_fork_jump_index);
|
||||||
|
new_bytecode[post_loop_fork_jump_index - 1] = (ByteCodeValueType)(new_bytecode.size() - post_loop_fork_jump_index);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// no maximum value set, repeat finding if possible
|
// no maximum value set, repeat finding if possible
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue