Jelajahi Sumber

LibWasm: Fix nested structured instruction parsing

Previously, the ip would not be propagated correctly, and we would
produce invalid jumps when more than one level of nesting was involved.
This makes loops work :P
Ali Mohammad Pur 4 tahun lalu
induk
melakukan
207379165f

+ 7 - 4
Userland/Libraries/LibWasm/AbstractMachine/Interpreter.cpp

@@ -28,10 +28,12 @@ void Interpreter::interpret(Configuration& configuration)
 
 
     while (current_ip_value < max_ip_value) {
     while (current_ip_value < max_ip_value) {
         auto& instruction = instructions[current_ip_value.value()];
         auto& instruction = instructions[current_ip_value.value()];
+        auto old_ip = current_ip_value;
         interpret(configuration, current_ip_value, instruction);
         interpret(configuration, current_ip_value, instruction);
         if (m_do_trap)
         if (m_do_trap)
             return;
             return;
-        ++current_ip_value;
+        if (current_ip_value == old_ip) // If no jump occurred
+            ++current_ip_value;
     }
     }
 }
 }
 
 
@@ -46,18 +48,19 @@ void Interpreter::branch_to_label(Configuration& configuration, LabelIndex index
     size_t drop_count = index.value() + 1;
     size_t drop_count = index.value() + 1;
 
 
     for (; !configuration.stack().is_empty();) {
     for (; !configuration.stack().is_empty();) {
-        auto entry = configuration.stack().pop();
+        auto& entry = configuration.stack().peek();
         if (entry.has<NonnullOwnPtr<Label>>()) {
         if (entry.has<NonnullOwnPtr<Label>>()) {
             if (drop_count-- == 0)
             if (drop_count-- == 0)
                 break;
                 break;
         }
         }
+        configuration.stack().pop();
     }
     }
 
 
     // Push results in reverse
     // Push results in reverse
     for (size_t i = results.size(); i > 0; --i)
     for (size_t i = results.size(); i > 0; --i)
         configuration.stack().push(move(static_cast<Vector<NonnullOwnPtr<Value>>&>(results)[i - 1]));
         configuration.stack().push(move(static_cast<Vector<NonnullOwnPtr<Value>>&>(results)[i - 1]));
 
 
-    configuration.ip() = label->continuation() + 1;
+    configuration.ip() = label->continuation();
 }
 }
 
 
 ReadonlyBytes Interpreter::load_from_memory(Configuration& configuration, const Instruction& instruction, size_t size)
 ReadonlyBytes Interpreter::load_from_memory(Configuration& configuration, const Instruction& instruction, size_t size)
@@ -321,7 +324,7 @@ void Interpreter::interpret(Configuration& configuration, InstructionPointer& ip
         auto& args = instruction.arguments().get<Instruction::StructuredInstructionArgs>();
         auto& args = instruction.arguments().get<Instruction::StructuredInstructionArgs>();
         if (args.block_type.kind() != BlockType::Empty)
         if (args.block_type.kind() != BlockType::Empty)
             arity = 1;
             arity = 1;
-        configuration.stack().push(make<Label>(arity, ip.value() + 1));
+        configuration.stack().push(make<Label>(arity, ip.value()));
         return;
         return;
     }
     }
     case Instructions::if_.value(): {
     case Instructions::if_.value(): {

+ 5 - 4
Userland/Libraries/LibWasm/Parser/Parser.cpp

@@ -82,7 +82,7 @@ struct ParseUntilAnyOfResult {
     Vector<T> values;
     Vector<T> values;
 };
 };
 template<typename T, u8... terminators, typename... Args>
 template<typename T, u8... terminators, typename... Args>
-static ParseResult<ParseUntilAnyOfResult<T>> parse_until_any_of(InputStream& stream, Args... args) requires(requires(InputStream& stream, Args... args) { T::parse(stream, args...); })
+static ParseResult<ParseUntilAnyOfResult<T>> parse_until_any_of(InputStream& stream, Args&... args) requires(requires(InputStream& stream, Args... args) { T::parse(stream, args...); })
 {
 {
     ScopeLogger<WASM_BINPARSER_DEBUG> logger;
     ScopeLogger<WASM_BINPARSER_DEBUG> logger;
     ReconsumableStream new_stream { stream };
     ReconsumableStream new_stream { stream };
@@ -305,7 +305,8 @@ ParseResult<Vector<Instruction>> Instruction::parse(InputStream& stream, Instruc
                 result.value().values.append(Instruction { Instructions::structured_end });
                 result.value().values.append(Instruction { Instructions::structured_end });
 
 
                 // Transform op(..., instr*) -> op(...) instr* op(end(ip))
                 // Transform op(..., instr*) -> op(...) instr* op(end(ip))
-                result.value().values.prepend(Instruction { opcode, StructuredInstructionArgs { BlockType { block_type.release_value() }, ++ip, {} } });
+                result.value().values.prepend(Instruction { opcode, StructuredInstructionArgs { BlockType { block_type.release_value() }, ip.value(), {} } });
+                ++ip;
                 return result.release_value().values;
                 return result.release_value().values;
             }
             }
 
 
@@ -314,7 +315,7 @@ ParseResult<Vector<Instruction>> Instruction::parse(InputStream& stream, Instruc
             instructions.append(result.release_value().values);
             instructions.append(result.release_value().values);
             instructions.append(Instruction { Instructions::structured_else });
             instructions.append(Instruction { Instructions::structured_else });
             ++ip;
             ++ip;
-            else_ip = ip;
+            else_ip = ip.value();
         }
         }
         // if with else
         // if with else
         {
         {
@@ -324,7 +325,7 @@ ParseResult<Vector<Instruction>> Instruction::parse(InputStream& stream, Instruc
             instructions.append(result.release_value().values);
             instructions.append(result.release_value().values);
             instructions.append(Instruction { Instructions::structured_end });
             instructions.append(Instruction { Instructions::structured_end });
             ++ip;
             ++ip;
-            end_ip = ip;
+            end_ip = ip.value();
         }
         }
 
 
         instructions.prepend(Instruction { opcode, StructuredInstructionArgs { BlockType { block_type.release_value() }, end_ip, else_ip } });
         instructions.prepend(Instruction { opcode, StructuredInstructionArgs { BlockType { block_type.release_value() }, end_ip, else_ip } });