diff options
author | Ali Mohammad Pur <ali.mpfard@gmail.com> | 2022-02-15 17:32:13 +0330 |
---|---|---|
committer | Ali Mohammad Pur <Ali.mpfard@gmail.com> | 2022-02-16 22:48:32 +0330 |
commit | eccdf4eb4bd30f789ca6bb810557e86a36400d62 (patch) | |
tree | 97671cc1a5cbd311edd68610805bdf9d3e144b06 /Userland/Libraries/LibWasm/AbstractMachine | |
parent | 385b07dcdafe4941e9986f93f7319a1df9f6c044 (diff) | |
download | serenity-eccdf4eb4bd30f789ca6bb810557e86a36400d62.zip |
LibWasm: Fix validation of if-else blocks
We were doing a number of things wrong:
- Switching to the parent context in the else meant that we couldn't
break out of the else section anymore
- We were not validating the resulting values, and so the stack was
in a relatively unknown state after 'else'
This commit fixes these issues :^)
Diffstat (limited to 'Userland/Libraries/LibWasm/AbstractMachine')
-rw-r--r-- | Userland/Libraries/LibWasm/AbstractMachine/Validator.cpp | 46 | ||||
-rw-r--r-- | Userland/Libraries/LibWasm/AbstractMachine/Validator.h | 2 |
2 files changed, 33 insertions, 15 deletions
diff --git a/Userland/Libraries/LibWasm/AbstractMachine/Validator.cpp b/Userland/Libraries/LibWasm/AbstractMachine/Validator.cpp index 5d05032059..076d4e5b3e 100644 --- a/Userland/Libraries/LibWasm/AbstractMachine/Validator.cpp +++ b/Userland/Libraries/LibWasm/AbstractMachine/Validator.cpp @@ -2382,20 +2382,28 @@ VALIDATE_INSTRUCTION(structured_end) m_context = m_parent_contexts.take_last(); auto last_block_type = m_entered_blocks.take_last(); - if (last_scope == ChildScopeKind::Block) { - auto details = m_block_details.take_last(); - // FIXME: Validate the returns. - return {}; + switch (last_scope) { + case ChildScopeKind::Block: + case ChildScopeKind::IfWithoutElse: + case ChildScopeKind::Else: + m_block_details.take_last(); + break; + case ChildScopeKind::IfWithElse: + return Errors::invalid("usage of if without an else clause that appears to have one anyway"); } - if (last_scope == ChildScopeKind::Else) { - auto details = m_block_details.take_last().details.get<BlockDetails::IfDetails>(); - if (details.true_branch_stack != stack) - return Errors::invalid("stack configuration after if-else", details.true_branch_stack.release_vector(), stack.release_vector()); + auto& results = last_block_type.results(); + if (results.size() > stack.size()) + return Errors::invalid_stack_state(); - return {}; + for (size_t i = 1; i <= results.size(); ++i) { + if (stack.take_last() != results[results.size() - i]) + return Errors::invalid_stack_state(); } + for (auto& result : results) + stack.append(result); + return {}; } @@ -2408,10 +2416,20 @@ VALIDATE_INSTRUCTION(structured_else) if (m_entered_scopes.last() != ChildScopeKind::IfWithElse) return Errors::invalid("usage of structured else"); + auto& block_type = m_entered_blocks.last(); + auto& results = block_type.results(); + + if (results.size() > stack.size()) + return Errors::invalid_stack_state(); + + for (size_t i = 1; i <= results.size(); ++i) { + if (stack.take_last() != results[results.size() - i]) + return Errors::invalid_stack_state(); + } + + auto& details = m_block_details.last().details.get<BlockDetails::IfDetails>(); m_entered_scopes.last() = ChildScopeKind::Else; - auto& if_details = m_block_details.last().details.get<BlockDetails::IfDetails>(); - if_details.true_branch_stack = exchange(stack, move(if_details.initial_stack)); - m_context = m_parent_contexts.last(); + stack = move(details.initial_stack); return {}; } @@ -2473,6 +2491,8 @@ VALIDATE_INSTRUCTION(if_) if (stack.is_empty() || !stack.take_last().is_of_kind(ValueType::I32)) return Errors::invalid_stack_state(); + auto stack_snapshot = stack; + auto& parameters = block_type.parameters(); if (stack.size() < parameters.size()) return Errors::invalid_stack_state(); @@ -2486,7 +2506,7 @@ VALIDATE_INSTRUCTION(if_) stack.append(parameter); m_entered_scopes.append(args.else_ip.has_value() ? ChildScopeKind::IfWithElse : ChildScopeKind::IfWithoutElse); - m_block_details.empend(stack.actual_size(), BlockDetails::IfDetails { stack, {} }); + m_block_details.empend(stack.actual_size(), BlockDetails::IfDetails { move(stack_snapshot) }); m_parent_contexts.append(m_context); m_entered_blocks.append(block_type); m_context.labels.prepend(ResultType { block_type.results() }); diff --git a/Userland/Libraries/LibWasm/AbstractMachine/Validator.h b/Userland/Libraries/LibWasm/AbstractMachine/Validator.h index 4e8010f98f..403f3a974b 100644 --- a/Userland/Libraries/LibWasm/AbstractMachine/Validator.h +++ b/Userland/Libraries/LibWasm/AbstractMachine/Validator.h @@ -260,7 +260,6 @@ private: enum class ChildScopeKind { Block, - Loop, IfWithoutElse, IfWithElse, Else, @@ -270,7 +269,6 @@ private: size_t initial_stack_size { 0 }; struct IfDetails { Stack initial_stack; - Stack true_branch_stack; }; Variant<IfDetails, Empty> details; }; |