Skip to content

Commit

Permalink
Validation of RJUMP* instructions
Browse files Browse the repository at this point in the history
  • Loading branch information
gumb0 authored and chfast committed Sep 28, 2022
1 parent 1815516 commit 58bfc9b
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 0 deletions.
44 changes: 44 additions & 0 deletions lib/evmone/eof.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <array>
#include <cassert>
#include <limits>
#include <vector>

namespace evmone
{
Expand Down Expand Up @@ -119,6 +120,41 @@ EOFValidationError validate_instructions(evmc_revision rev, bytes_view code) noe
return EOFValidationError::success;
}

bool validate_rjump_destinations(
const EOF1Header& header, bytes_view::const_iterator container) noexcept
{
// Collect relative jump destinations and immediate locations
std::vector<size_t> rjumpdests;
std::vector<bool> immediate_map(header.code_end());
for (auto i = header.code_begin(); i < header.code_end(); ++i)
{
const auto op = container[i];

if (op == OP_RJUMP || op == OP_RJUMPI)
{
const auto offset_hi = container[i + 1];
const auto offset_lo = container[i + 2];
const auto offset = static_cast<int16_t>((offset_hi << 8) + offset_lo);
const auto jumpdest = static_cast<int32_t>(i) + 3 + offset;
if (jumpdest < static_cast<int32_t>(header.code_begin()) ||
jumpdest >= static_cast<int32_t>(header.code_end()))
return false;
rjumpdests.push_back(static_cast<size_t>(jumpdest));
}

const auto imm_size = instr::traits[op].immediate_size;
std::fill_n(immediate_map.begin() + static_cast<ptrdiff_t>(i) + 1, imm_size, true);
i += imm_size;
}

// Check relative jump destinations against immediate locations.
for (const auto rjumpdest : rjumpdests)
if (immediate_map[rjumpdest])
return false;

return true;
}

std::pair<EOF1Header, EOFValidationError> validate_eof1(
evmc_revision rev, bytes_view container) noexcept
{
Expand All @@ -133,6 +169,9 @@ std::pair<EOF1Header, EOFValidationError> validate_eof1(
if (error_instr != EOFValidationError::success)
return {{}, error_instr};

if (!validate_rjump_destinations(header, container.begin()))
return {{}, EOFValidationError::invalid_rjump_destination};

return {header, EOFValidationError::success};
}

Expand All @@ -148,6 +187,11 @@ size_t EOF1Header::code_begin() const noexcept
return 10; // MAGIC + VERSION + SECTION_ID + SIZE + SECTION_ID + SIZE + TERMINATOR
}

size_t EOF1Header::code_end() const noexcept
{
return code_begin() + code_size;
}

bool is_eof_code(bytes_view code) noexcept
{
return code.size() > 1 && code[0] == MAGIC[0] && code[1] == MAGIC[1];
Expand Down
2 changes: 2 additions & 0 deletions lib/evmone/eof.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ struct EOF1Header

/// Returns offset of code section start.
[[nodiscard]] EVMC_EXPORT size_t code_begin() const noexcept;
[[nodiscard]] EVMC_EXPORT size_t code_end() const noexcept;
};

/// Checks if code starts with EOF FORMAT + MAGIC, doesn't validate the format.
Expand Down Expand Up @@ -48,6 +49,7 @@ enum class EOFValidationError
invalid_section_bodies_size,
undefined_instruction,
missing_terminating_instruction,
invalid_rjump_destination,

impossible,
};
Expand Down

0 comments on commit 58bfc9b

Please sign in to comment.