LibWasm+Everywhere: Make the instruction count limit configurable
...and enable it for LibWeb and test-wasm. Note that `wasm` will not be limited by this.
This commit is contained in:
parent
70b94f58b2
commit
65cd5526cb
Notes:
sideshowbarker
2024-07-18 08:54:43 +09:00
Author: https://github.com/alimpfard Commit: https://github.com/SerenityOS/serenity/commit/65cd5526cbf
6 changed files with 25 additions and 3 deletions
|
@ -34,6 +34,7 @@ public:
|
|||
explicit WebAssemblyModule(JS::Object& prototype)
|
||||
: JS::Object(prototype)
|
||||
{
|
||||
m_machine.enable_instruction_count_limit();
|
||||
}
|
||||
|
||||
static Wasm::AbstractMachine& machine() { return m_machine; }
|
||||
|
|
|
@ -128,6 +128,8 @@ InstantiationResult AbstractMachine::instantiate(Module const& module, Vector<Ex
|
|||
module.for_each_section_of_type<GlobalSection>([&](auto& global_section) {
|
||||
for (auto& entry : global_section.entries()) {
|
||||
Configuration config { m_store };
|
||||
if (m_should_limit_instruction_count)
|
||||
config.enable_instruction_count_limit();
|
||||
config.set_frame(Frame {
|
||||
auxiliary_instance,
|
||||
Vector<Value> {},
|
||||
|
@ -153,6 +155,8 @@ InstantiationResult AbstractMachine::instantiate(Module const& module, Vector<Ex
|
|||
Vector<Reference> references;
|
||||
for (auto& entry : segment.init) {
|
||||
Configuration config { m_store };
|
||||
if (m_should_limit_instruction_count)
|
||||
config.enable_instruction_count_limit();
|
||||
config.set_frame(Frame {
|
||||
main_module_instance,
|
||||
Vector<Value> {},
|
||||
|
@ -204,6 +208,8 @@ InstantiationResult AbstractMachine::instantiate(Module const& module, Vector<Ex
|
|||
return IterationDecision::Break;
|
||||
}
|
||||
Configuration config { m_store };
|
||||
if (m_should_limit_instruction_count)
|
||||
config.enable_instruction_count_limit();
|
||||
config.set_frame(Frame {
|
||||
main_module_instance,
|
||||
Vector<Value> {},
|
||||
|
@ -262,6 +268,8 @@ InstantiationResult AbstractMachine::instantiate(Module const& module, Vector<Ex
|
|||
segment.value().visit(
|
||||
[&](DataSection::Data::Active const& data) {
|
||||
Configuration config { m_store };
|
||||
if (m_should_limit_instruction_count)
|
||||
config.enable_instruction_count_limit();
|
||||
config.set_frame(Frame {
|
||||
main_module_instance,
|
||||
Vector<Value> {},
|
||||
|
@ -439,6 +447,8 @@ Result AbstractMachine::invoke(FunctionAddress address, Vector<Value> arguments)
|
|||
Result AbstractMachine::invoke(Interpreter& interpreter, FunctionAddress address, Vector<Value> arguments)
|
||||
{
|
||||
Configuration configuration { m_store };
|
||||
if (m_should_limit_instruction_count)
|
||||
configuration.enable_instruction_count_limit();
|
||||
return configuration.call(interpreter, address, move(arguments));
|
||||
}
|
||||
|
||||
|
|
|
@ -505,10 +505,13 @@ public:
|
|||
auto& store() const { return m_store; }
|
||||
auto& store() { return m_store; }
|
||||
|
||||
void enable_instruction_count_limit() { m_should_limit_instruction_count = true; }
|
||||
|
||||
private:
|
||||
Optional<InstantiationError> allocate_all_initial_phase(Module const&, ModuleInstance&, Vector<ExternValue>&, Vector<Value>& global_values);
|
||||
Optional<InstantiationError> allocate_all_final_phase(Module const&, ModuleInstance&, Vector<Vector<Reference>>& elements);
|
||||
Store m_store;
|
||||
bool m_should_limit_instruction_count { false };
|
||||
};
|
||||
|
||||
class Linker {
|
||||
|
|
|
@ -37,12 +37,15 @@ void BytecodeInterpreter::interpret(Configuration& configuration)
|
|||
auto& instructions = configuration.frame().expression().instructions();
|
||||
auto max_ip_value = InstructionPointer { instructions.size() };
|
||||
auto& current_ip_value = configuration.ip();
|
||||
auto const should_limit_instruction_count = configuration.should_limit_instruction_count();
|
||||
u64 executed_instructions = 0;
|
||||
|
||||
while (current_ip_value < max_ip_value) {
|
||||
if (executed_instructions++ >= Constants::max_allowed_executed_instructions_per_call) [[unlikely]] {
|
||||
m_trap = Trap { "Exceeded maximum allowed number of instructions" };
|
||||
return;
|
||||
if (should_limit_instruction_count) {
|
||||
if (executed_instructions++ >= Constants::max_allowed_executed_instructions_per_call) [[unlikely]] {
|
||||
m_trap = Trap { "Exceeded maximum allowed number of instructions" };
|
||||
return;
|
||||
}
|
||||
}
|
||||
auto& instruction = instructions[current_ip_value.value()];
|
||||
auto old_ip = current_ip_value;
|
||||
|
|
|
@ -61,6 +61,9 @@ public:
|
|||
Result call(Interpreter&, FunctionAddress, Vector<Value> arguments);
|
||||
Result execute(Interpreter&);
|
||||
|
||||
void enable_instruction_count_limit() { m_should_limit_instruction_count = true; }
|
||||
bool should_limit_instruction_count() const { return m_should_limit_instruction_count; }
|
||||
|
||||
void dump_stack();
|
||||
|
||||
private:
|
||||
|
@ -69,6 +72,7 @@ private:
|
|||
Stack m_stack;
|
||||
size_t m_depth { 0 };
|
||||
InstructionPointer m_ip;
|
||||
bool m_should_limit_instruction_count { false };
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ namespace Web::Bindings {
|
|||
WebAssemblyObject::WebAssemblyObject(JS::GlobalObject& global_object)
|
||||
: Object(*global_object.object_prototype())
|
||||
{
|
||||
s_abstract_machine.enable_instruction_count_limit();
|
||||
}
|
||||
|
||||
void WebAssemblyObject::initialize(JS::GlobalObject& global_object)
|
||||
|
|
Loading…
Add table
Reference in a new issue