Explorar o código

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 %!s(int64=4) %!d(string=hai) anos
pai
achega
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) {
         auto& instruction = instructions[current_ip_value.value()];
+        auto old_ip = current_ip_value;
         interpret(configuration, current_ip_value, instruction);
         if (m_do_trap)
             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;
 
     for (; !configuration.stack().is_empty();) {
-        auto entry = configuration.stack().pop();
+        auto& entry = configuration.stack().peek();
         if (entry.has<NonnullOwnPtr<Label>>()) {
             if (drop_count-- == 0)
                 break;
         }
+        configuration.stack().pop();
     }
 
     // Push results in reverse
     for (size_t i = results.size(); i > 0; --i)
         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)
@@ -321,7 +324,7 @@ void Interpreter::interpret(Configuration& configuration, InstructionPointer& ip
         auto& args = instruction.arguments().get<Instruction::StructuredInstructionArgs>();
         if (args.block_type.kind() != BlockType::Empty)
             arity = 1;
-        configuration.stack().push(make<Label>(arity, ip.value() + 1));
+        configuration.stack().push(make<Label>(arity, ip.value()));
         return;
     }
     case Instructions::if_.value(): {

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

@@ -82,7 +82,7 @@ struct ParseUntilAnyOfResult {
     Vector<T> values;
 };
 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;
     ReconsumableStream new_stream { stream };
@@ -305,7 +305,8 @@ ParseResult<Vector<Instruction>> Instruction::parse(InputStream& stream, Instruc
                 result.value().values.append(Instruction { Instructions::structured_end });
 
                 // 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;
             }
 
@@ -314,7 +315,7 @@ ParseResult<Vector<Instruction>> Instruction::parse(InputStream& stream, Instruc
             instructions.append(result.release_value().values);
             instructions.append(Instruction { Instructions::structured_else });
             ++ip;
-            else_ip = ip;
+            else_ip = ip.value();
         }
         // if with else
         {
@@ -324,7 +325,7 @@ ParseResult<Vector<Instruction>> Instruction::parse(InputStream& stream, Instruc
             instructions.append(result.release_value().values);
             instructions.append(Instruction { Instructions::structured_end });
             ++ip;
-            end_ip = ip;
+            end_ip = ip.value();
         }
 
         instructions.prepend(Instruction { opcode, StructuredInstructionArgs { BlockType { block_type.release_value() }, end_ip, else_ip } });