diff --git a/Tests/LibWasm/test-wasm.cpp b/Tests/LibWasm/test-wasm.cpp index 2cb6abe619..d0b16d7d70 100644 --- a/Tests/LibWasm/test-wasm.cpp +++ b/Tests/LibWasm/test-wasm.cpp @@ -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; } diff --git a/Userland/Libraries/LibWasm/AbstractMachine/AbstractMachine.cpp b/Userland/Libraries/LibWasm/AbstractMachine/AbstractMachine.cpp index 07a81d7fe9..d923987bdc 100644 --- a/Userland/Libraries/LibWasm/AbstractMachine/AbstractMachine.cpp +++ b/Userland/Libraries/LibWasm/AbstractMachine/AbstractMachine.cpp @@ -128,6 +128,8 @@ InstantiationResult AbstractMachine::instantiate(Module const& module, Vector([&](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 {}, @@ -153,6 +155,8 @@ InstantiationResult AbstractMachine::instantiate(Module const& module, Vector 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 {}, @@ -204,6 +208,8 @@ InstantiationResult AbstractMachine::instantiate(Module const& module, Vector {}, @@ -262,6 +268,8 @@ InstantiationResult AbstractMachine::instantiate(Module const& module, Vector {}, @@ -439,6 +447,8 @@ Result AbstractMachine::invoke(FunctionAddress address, Vector arguments) Result AbstractMachine::invoke(Interpreter& interpreter, FunctionAddress address, Vector arguments) { Configuration configuration { m_store }; + if (m_should_limit_instruction_count) + configuration.enable_instruction_count_limit(); return configuration.call(interpreter, address, move(arguments)); } diff --git a/Userland/Libraries/LibWasm/AbstractMachine/AbstractMachine.h b/Userland/Libraries/LibWasm/AbstractMachine/AbstractMachine.h index af9acb1f67..659a3bae78 100644 --- a/Userland/Libraries/LibWasm/AbstractMachine/AbstractMachine.h +++ b/Userland/Libraries/LibWasm/AbstractMachine/AbstractMachine.h @@ -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 allocate_all_initial_phase(Module const&, ModuleInstance&, Vector&, Vector& global_values); Optional allocate_all_final_phase(Module const&, ModuleInstance&, Vector>& elements); Store m_store; + bool m_should_limit_instruction_count { false }; }; class Linker { diff --git a/Userland/Libraries/LibWasm/AbstractMachine/BytecodeInterpreter.cpp b/Userland/Libraries/LibWasm/AbstractMachine/BytecodeInterpreter.cpp index 06a87b010d..8db9b852dc 100644 --- a/Userland/Libraries/LibWasm/AbstractMachine/BytecodeInterpreter.cpp +++ b/Userland/Libraries/LibWasm/AbstractMachine/BytecodeInterpreter.cpp @@ -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; diff --git a/Userland/Libraries/LibWasm/AbstractMachine/Configuration.h b/Userland/Libraries/LibWasm/AbstractMachine/Configuration.h index 04cef62746..580ad526e5 100644 --- a/Userland/Libraries/LibWasm/AbstractMachine/Configuration.h +++ b/Userland/Libraries/LibWasm/AbstractMachine/Configuration.h @@ -61,6 +61,9 @@ public: Result call(Interpreter&, FunctionAddress, Vector 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 }; }; } diff --git a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyObject.cpp b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyObject.cpp index 96654696eb..d383994ad1 100644 --- a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyObject.cpp +++ b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyObject.cpp @@ -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)