Skip to content

Commit

Permalink
Assert against overflow in header.data_offset
Browse files Browse the repository at this point in the history
  • Loading branch information
pdobacz committed May 24, 2024
1 parent 7ad882c commit 7f81d8f
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 10 deletions.
2 changes: 2 additions & 0 deletions lib/evmone/eof.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,8 @@ std::variant<EOF1Header, EOFValidationError> validate_header(
container_offsets.emplace_back(static_cast<uint16_t>(offset));
offset += container_size;
}
// NOTE: assertion always satisfied only as long as initcode limits apply (48K).
assert(offset <= std::numeric_limits<uint16_t>::max());
const auto data_offset = static_cast<uint16_t>(offset);

return EOF1Header{
Expand Down
11 changes: 7 additions & 4 deletions test/unittests/eof_validation_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1205,9 +1205,12 @@ TEST_F(eof_validation, EOF1_subcontainer_containing_unreachable_code_sections)

TEST_F(eof_validation, max_nested_containers)
{
bytecode code = eof_bytecode(OP_INVALID);
while (code.size() <= std::numeric_limits<uint16_t>::max())
code = eof_bytecode(OP_INVALID).container(code);

bytecode code{};
bytecode nextcode = eof_bytecode(OP_INVALID);
while (nextcode.size() <= std::numeric_limits<uint16_t>::max())
{
code = nextcode;
nextcode = eof_bytecode(OP_INVALID).container(nextcode);
}
add_test_case(code, EOFValidationError::success);
}
12 changes: 6 additions & 6 deletions test/unittests/state_transition_eof_create_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -670,18 +670,18 @@ TEST_F(state_transition, eofcreate_not_enough_gas_for_initcode_charge)

const auto init_code = returncontract(0, 0, 0);
auto init_container = eof_bytecode(init_code, 2).container(deploy_container);
// add max size data
const auto init_data =
bytes(std::numeric_limits<uint16_t>::max() - bytecode(init_container).size(), 0);
init_container.data(init_data);
EXPECT_EQ(bytecode(init_container).size(), std::numeric_limits<uint16_t>::max());
const uint16_t init_data_size = std::numeric_limits<uint16_t>::max() / 2 -
static_cast<uint16_t>(bytecode(init_container).size());
const auto init_data = bytes(init_data_size, 0);
init_container.data(init_data, init_data_size);
EXPECT_EQ(bytecode(init_container).size(), std::numeric_limits<uint16_t>::max() / 2);

const auto factory_code = sstore(0, eofcreate().container(0).salt(Salt)) + OP_STOP;
const auto factory_container = eof_bytecode(factory_code, 4).container(init_container);

tx.to = To;
// tx intrinsic cost + EOFCREATE cost + initcode charge - not enough for pushes before EOFCREATE
tx.gas_limit = 21'000 + 32'000 + (std::numeric_limits<uint16_t>::max() + 31) / 32 * 6;
tx.gas_limit = 21'000 + 32'000 + (std::numeric_limits<uint16_t>::max() / 2 + 31) / 32 * 6;

pre.insert(*tx.to, {.nonce = 1, .code = factory_container});

Expand Down

0 comments on commit 7f81d8f

Please sign in to comment.