diff --git a/circle.yml b/circle.yml index a0df698d4c..ab7ad9d3b0 100644 --- a/circle.yml +++ b/circle.yml @@ -129,6 +129,9 @@ commands: download_execution_spec_tests: parameters: + repo: + type: string + default: ethereum/execution-spec-tests release: type: string fixtures_suffix: @@ -139,7 +142,7 @@ commands: name: "Download execution-spec-tests: <>" working_directory: ~/spec-tests command: | - curl -L https://github.com/ethereum/execution-spec-tests/releases/download/<>/fixtures_<>.tar.gz | tar -xz + curl -L https://github.com/<>/releases/download/<>/fixtures_<>.tar.gz | tar -xz ls -l build: @@ -398,7 +401,8 @@ jobs: steps: - build - download_execution_spec_tests: - release: eip7692@v1.0.3 + repo: ipsilon/execution-spec-tests + release: eip7692@v1.0.4+ipsilon_bf37249b fixtures_suffix: eip7692 - run: name: "EOF pre-release execution spec tests (state_tests)" diff --git a/lib/evmone/eof.cpp b/lib/evmone/eof.cpp index 5afb055051..20794aba4b 100644 --- a/lib/evmone/eof.cpp +++ b/lib/evmone/eof.cpp @@ -37,6 +37,9 @@ constexpr auto REL_OFFSET_SIZE = sizeof(int16_t); constexpr auto STACK_SIZE_LIMIT = 1024; constexpr uint8_t NON_RETURNING_FUNCTION = 0x80; +constexpr size_t MAX_CODE_SIZE = 0x6000; +constexpr size_t MAX_INITCODE_SIZE = 2 * MAX_CODE_SIZE; + using EOFSectionHeaders = std::array, MAX_SECTION + 1>; size_t eof_header_size(const EOFSectionHeaders& headers) noexcept @@ -592,6 +595,10 @@ EOFValidationError validate_eof1( bytes_view bytes; ContainerKind kind; }; + + if (main_container.size() > MAX_INITCODE_SIZE) + return EOFValidationError::container_size_above_limit; + // Queue of containers left to process std::queue container_queue; @@ -738,6 +745,12 @@ std::variant validate_header( if (rev < EVMC_PRAGUE) return EOFValidationError::eof_version_unknown; + // `offset` variable handled below is known to not be greater than the container size, as + // checked in `validate_section_headers`. Combined with the requirement for the container + // size to not exceed MAX_INITCODE_SIZE (checked before `validate-header` is called), + // this allows us to cast `offset` to narrower integers. + assert(container.size() <= MAX_INITCODE_SIZE); + const auto section_headers_or_error = validate_section_headers(container); if (const auto* error = std::get_if(§ion_headers_or_error)) return *error; @@ -757,6 +770,7 @@ std::variant validate_header( std::vector code_offsets; const auto type_section_size = section_headers[TYPE_SECTION][0]; auto offset = header_size + type_section_size; + for (const auto code_size : code_sizes) { assert(offset <= std::numeric_limits::max()); @@ -768,10 +782,11 @@ std::variant validate_header( std::vector container_offsets; for (const auto container_size : container_sizes) { + assert(offset <= std::numeric_limits::max()); 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); @@ -971,6 +986,8 @@ std::string_view get_error_message(EOFValidationError err) noexcept return "ambiguous_container_kind"; case EOFValidationError::incompatible_container_kind: return "incompatible_container_kind"; + case EOFValidationError::container_size_above_limit: + return "container_size_above_limit"; case EOFValidationError::impossible: return "impossible"; } diff --git a/lib/evmone/eof.hpp b/lib/evmone/eof.hpp index 61af8592df..8b81014308 100644 --- a/lib/evmone/eof.hpp +++ b/lib/evmone/eof.hpp @@ -141,6 +141,7 @@ enum class EOFValidationError toplevel_container_truncated, ambiguous_container_kind, incompatible_container_kind, + container_size_above_limit, impossible, }; diff --git a/test/unittests/eof_validation.cpp b/test/unittests/eof_validation.cpp index f8d0583c21..e94f7a68d4 100644 --- a/test/unittests/eof_validation.cpp +++ b/test/unittests/eof_validation.cpp @@ -93,6 +93,8 @@ std::string_view get_tests_error_message(EOFValidationError err) noexcept return "EOF_AmbiguousContainerKind"; case EOFValidationError::incompatible_container_kind: return "EOF_IncompatibleContainerKind"; + case EOFValidationError::container_size_above_limit: + return "EOF_ContainerSizeAboveLimit"; case EOFValidationError::impossible: return "impossible"; } diff --git a/test/unittests/eof_validation_test.cpp b/test/unittests/eof_validation_test.cpp index fa0f77c29c..fbab577321 100644 --- a/test/unittests/eof_validation_test.cpp +++ b/test/unittests/eof_validation_test.cpp @@ -1211,9 +1211,11 @@ TEST_F(eof_validation, EOF1_subcontainer_containing_unreachable_code_sections) TEST_F(eof_validation, max_nested_containers) { + constexpr size_t MAX_CODE_SIZE = 0x6000; + constexpr size_t MAX_INITCODE_SIZE = 2 * MAX_CODE_SIZE; bytecode code{}; bytecode nextcode = eof_bytecode(OP_INVALID); - while (nextcode.size() <= std::numeric_limits::max()) + while (nextcode.size() <= MAX_INITCODE_SIZE) { code = nextcode; nextcode = eof_bytecode(OP_INVALID).container(nextcode);