summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibWasm/AbstractMachine
diff options
context:
space:
mode:
authorAli Mohammad Pur <ali.mpfard@gmail.com>2022-02-15 17:32:13 +0330
committerAli Mohammad Pur <Ali.mpfard@gmail.com>2022-02-16 22:48:32 +0330
commiteccdf4eb4bd30f789ca6bb810557e86a36400d62 (patch)
tree97671cc1a5cbd311edd68610805bdf9d3e144b06 /Userland/Libraries/LibWasm/AbstractMachine
parent385b07dcdafe4941e9986f93f7319a1df9f6c044 (diff)
downloadserenity-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.cpp46
-rw-r--r--Userland/Libraries/LibWasm/AbstractMachine/Validator.h2
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;
};