Skip to content

Commit

Permalink
Refactor validate_successors()
Browse files Browse the repository at this point in the history
  • Loading branch information
chfast committed Mar 16, 2023
1 parent 193136e commit 1b39d8d
Showing 1 changed file with 25 additions and 26 deletions.
51 changes: 25 additions & 26 deletions lib/evmone/eof.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -334,8 +334,7 @@ std::pair<EOFValidationError, int32_t> validate_max_stack_height(
if (stack_height < stack_height_required)
return {EOFValidationError::stack_underflow, -1};

// Target locations of control flow.
std::vector<size_t> successors;
stack_height += stack_height_change;

// Determine size of immediate, including the special case of RJUMPV.
const size_t imm_size = (opcode == OP_RJUMPV) ? (1 + /*count*/ size_t{code[i + 1]} * 2) :
Expand All @@ -344,49 +343,49 @@ std::pair<EOFValidationError, int32_t> validate_max_stack_height(
// Mark immediate locations.
std::fill_n(&stack_heights[i + 1], imm_size, LOC_IMMEDIATE);

// Validates the successor instruction and updates its stack height.
const auto validate_successor = [&stack_heights, &worklist](size_t successor_offset,
int32_t expected_stack_height) {
auto& successor_stack_height = stack_heights[successor_offset];
if (successor_stack_height == LOC_UNVISITED)
{
successor_stack_height = expected_stack_height;
worklist.push(successor_offset);
return true;
}
else
return successor_stack_height == expected_stack_height;
};

const auto next = i + imm_size + 1; // Offset of the next instruction (may be invalid).

// Check validity of next instruction. We skip RJUMP and terminating instructions.
if (!instr::traits[opcode].is_terminating && opcode != OP_RJUMP)
{
const auto next = i + imm_size + 1;
if (next >= code.size())
return {EOFValidationError::no_terminating_instruction, -1};

successors.push_back(next);
validate_successor(next, stack_height);
}

// Collect non-fallthrough successors of relative jumps.
// Validate non-fallthrough successors of relative jumps.
if (opcode == OP_RJUMP || opcode == OP_RJUMPI)
{
// Insert jump target.
const auto target_rel_offset = read_int16_be(&code[i + 1]);
successors.push_back(
static_cast<size_t>(static_cast<int32_t>(i) + target_rel_offset + 3));
validate_successor(
static_cast<size_t>(static_cast<int32_t>(i) + target_rel_offset + 3), stack_height);
}
else if (opcode == OP_RJUMPV)
{
const auto count = code[i + 1];

const auto pc_post_instruction = i + imm_size + 1;
// Insert all jump targets.
// Validate all jump targets.
for (size_t k = 0; k < count; ++k)
{
const auto target_rel_offset = read_int16_be(&code[i + k * 2 + 2]);
successors.push_back(static_cast<size_t>(
static_cast<int32_t>(pc_post_instruction) + target_rel_offset));
}
}

stack_height += stack_height_change;

for (const auto& s : successors)
{
if (stack_heights[s] == LOC_UNVISITED)
{
stack_heights[s] = stack_height;
worklist.push(s);
validate_successor(
static_cast<size_t>(static_cast<int32_t>(next) + target_rel_offset),
stack_height);
}
else if (stack_heights[s] != stack_height)
return {EOFValidationError::stack_height_mismatch, -1};
}

if (opcode == OP_RETF && stack_height != code_types[func_index].outputs)
Expand Down

0 comments on commit 1b39d8d

Please sign in to comment.