Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix max stack growth overflow #219

Merged
merged 2 commits into from
Dec 3, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions lib/evmone/analysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,15 @@ struct block_analysis
explicit block_analysis(size_t index) noexcept : begin_block_index{index} {}

/// Close the current block by producing compressed information about the block.
block_info close() const noexcept
[[nodiscard]] block_info close() const noexcept
{
static constexpr auto stack_req_max = std::numeric_limits<int16_t>::max();
static constexpr auto stack_param_max = std::numeric_limits<int16_t>::max();

const auto final_stack_req =
stack_req <= stack_req_max ? static_cast<int16_t>(stack_req) : stack_req_max;
const auto final_stack_max_growth = static_cast<int16_t>(stack_max_growth);
stack_req <= stack_param_max ? static_cast<int16_t>(stack_req) : stack_param_max;
const auto final_stack_max_growth = stack_max_growth <= stack_param_max ?
static_cast<int16_t>(stack_max_growth) :
stack_param_max;
return {gas_cost, final_stack_req, final_stack_max_growth};
}
};
Expand Down
26 changes: 26 additions & 0 deletions test/unittests/evm_other_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,32 @@ TEST_F(evm_other, evmone_block_stack_req_overflow)
EXPECT_STATUS(EVMC_STACK_UNDERFLOW);
}

TEST_F(evm_other, evmone_block_max_stack_growth_overflow)
{
// This tests constructs a code with single basic block which stack max growth is > int16 max.
// Such basic block can cause int16_t overflow during analysis.

constexpr auto test_max_code_size = 1024 * 1024u + 1;

bytes code_buffer(test_max_code_size, uint8_t{OP_MSIZE});

for (auto max_stack_growth : {32767u, 32768u, 65535u, 65536u, test_max_code_size - 1})
{
execute({code_buffer.data(), max_stack_growth});
EXPECT_STATUS(EVMC_STACK_OVERFLOW);

code_buffer[max_stack_growth] = OP_JUMPDEST;
execute({code_buffer.data(), max_stack_growth + 1});
EXPECT_STATUS(EVMC_STACK_OVERFLOW);

code_buffer[max_stack_growth] = OP_STOP;
execute({code_buffer.data(), max_stack_growth + 1});
EXPECT_STATUS(EVMC_STACK_OVERFLOW);

code_buffer[max_stack_growth] = OP_MSIZE; // Restore original opcode.
}
}

TEST_F(evm_other, loop_full_of_jumpdests)
{
// The code is a simple loop with a counter taken from the input or a constant (325) if the
Expand Down