From 7f81d8fd9a7734f73d65218ec91a055a989ca386 Mon Sep 17 00:00:00 2001 From: pdobacz <5735525+pdobacz@users.noreply.github.com> Date: Wed, 15 May 2024 18:23:22 +0200 Subject: [PATCH] Assert against overflow in header.data_offset --- lib/evmone/eof.cpp | 2 ++ test/unittests/eof_validation_test.cpp | 11 +++++++---- test/unittests/state_transition_eof_create_test.cpp | 12 ++++++------ 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/lib/evmone/eof.cpp b/lib/evmone/eof.cpp index ec086f4f4c..4ff58255a0 100644 --- a/lib/evmone/eof.cpp +++ b/lib/evmone/eof.cpp @@ -296,6 +296,8 @@ std::variant validate_header( container_offsets.emplace_back(static_cast(offset)); offset += container_size; } + // NOTE: assertion always satisfied only as long as initcode limits apply (48K). + assert(offset <= std::numeric_limits::max()); const auto data_offset = static_cast(offset); return EOF1Header{ diff --git a/test/unittests/eof_validation_test.cpp b/test/unittests/eof_validation_test.cpp index 1342aae4e5..65852f4aa2 100644 --- a/test/unittests/eof_validation_test.cpp +++ b/test/unittests/eof_validation_test.cpp @@ -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::max()) - code = eof_bytecode(OP_INVALID).container(code); - + bytecode code{}; + bytecode nextcode = eof_bytecode(OP_INVALID); + while (nextcode.size() <= std::numeric_limits::max()) + { + code = nextcode; + nextcode = eof_bytecode(OP_INVALID).container(nextcode); + } add_test_case(code, EOFValidationError::success); } diff --git a/test/unittests/state_transition_eof_create_test.cpp b/test/unittests/state_transition_eof_create_test.cpp index eaa726e167..1a62083bc9 100644 --- a/test/unittests/state_transition_eof_create_test.cpp +++ b/test/unittests/state_transition_eof_create_test.cpp @@ -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::max() - bytecode(init_container).size(), 0); - init_container.data(init_data); - EXPECT_EQ(bytecode(init_container).size(), std::numeric_limits::max()); + const uint16_t init_data_size = std::numeric_limits::max() / 2 - + static_cast(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::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::max() + 31) / 32 * 6; + tx.gas_limit = 21'000 + 32'000 + (std::numeric_limits::max() / 2 + 31) / 32 * 6; pre.insert(*tx.to, {.nonce = 1, .code = factory_container});