Skip to content

Commit

Permalink
EOF: limit validated container size to MAX_INITCODE_SIZE
Browse files Browse the repository at this point in the history
  • Loading branch information
pdobacz committed Jun 14, 2024
1 parent 209aee1 commit fe1e32d
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 2 deletions.
24 changes: 22 additions & 2 deletions lib/evmone/eof.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<std::vector<uint16_t>, MAX_SECTION + 1>;

size_t eof_header_size(const EOFSectionHeaders& headers) noexcept
Expand Down Expand Up @@ -579,6 +582,10 @@ EOFValidationError validate_eof1(evmc_revision rev, bytes_view main_container) n
bytes_view bytes;
bool referenced_by_eofcreate = false;
};

if (main_container.size() > MAX_INITCODE_SIZE)
return EOFValidationError::container_size_above_limit;

// Queue of containers left to process
std::queue<ContainerValidation> container_queue;
container_queue.push({main_container, false});
Expand Down Expand Up @@ -726,11 +733,20 @@ std::variant<EOF1Header, EOFValidationError> validate_header(
std::vector<uint16_t> code_offsets;
const auto type_section_size = section_headers[TYPE_SECTION][0];
auto offset = header_size + type_section_size;

// `offset` is being checked to not overflow the container size. Combined with the
// requirement for the container size to not exceed MAX_INITCODE_SIZE, this allows
// us to cast to a narrower integer.
if (offset > container.size())
return EOFValidationError::invalid_section_bodies_size;

for (const auto code_size : code_sizes)
{
assert(offset <= std::numeric_limits<uint16_t>::max());
code_offsets.emplace_back(static_cast<uint16_t>(offset));
offset += code_size;
if (offset > container.size())
return EOFValidationError::invalid_section_bodies_size;
}

const auto& container_sizes = section_headers[CONTAINER_SECTION];
Expand All @@ -739,9 +755,11 @@ std::variant<EOF1Header, EOFValidationError> validate_header(
{
container_offsets.emplace_back(static_cast<uint16_t>(offset));
offset += container_size;

if (offset > container.size())
return EOFValidationError::invalid_section_bodies_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 Expand Up @@ -935,6 +953,8 @@ std::string_view get_error_message(EOFValidationError err) noexcept
return "eofcreate_with_truncated_container";
case EOFValidationError::toplevel_container_truncated:
return "toplevel_container_truncated";
case EOFValidationError::container_size_above_limit:
return "container_size_above_limit";
case EOFValidationError::impossible:
return "impossible";
}
Expand Down
1 change: 1 addition & 0 deletions lib/evmone/eof.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ enum class EOFValidationError
invalid_container_section_index,
eofcreate_with_truncated_container,
toplevel_container_truncated,
container_size_above_limit,

impossible,
};
Expand Down
2 changes: 2 additions & 0 deletions test/unittests/eof_validation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ std::string_view get_tests_error_message(EOFValidationError err) noexcept
return "EOF_EofCreateWithTruncatedContainer";
case EOFValidationError::toplevel_container_truncated:
return "EOF_ToplevelContainerTruncated";
case EOFValidationError::container_size_above_limit:
return "EOF_ContainerSizeAboveLimit";
case EOFValidationError::impossible:
return "impossible";
}
Expand Down

0 comments on commit fe1e32d

Please sign in to comment.