mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-10 02:54:54 +03:00
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 :^)
This commit is contained in:
parent
385b07dcda
commit
eccdf4eb4b
Notes:
sideshowbarker
2024-07-18 00:34:07 +09:00
Author: https://github.com/alimpfard Commit: https://github.com/SerenityOS/serenity/commit/eccdf4eb4b Pull-request: https://github.com/SerenityOS/serenity/pull/12548 Reviewed-by: https://github.com/awesomekling Reviewed-by: https://github.com/linusg
@ -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() });
|
||||
|
@ -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;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user