Skip to content

Commit

Permalink
precompiles: Improve output buffer handling
Browse files Browse the repository at this point in the history
Replace the fixed-size on-stack temporary buffer for precompiles
with a heap-allocated buffer big enough to handle properly any
precompile invocation.

This actually keeps the number of allocations the same. Previously
the contents of the on-stack buffer were copied to heap
by the Result constructor. Now we are creating the heap buffer
in the first place and pass the ownership of it to the Result.

This fixes out-of-bounds memory accesses often being found by fuzzers.
  • Loading branch information
chfast committed Jul 14, 2024
1 parent 70ca837 commit e186095
Showing 1 changed file with 8 additions and 13 deletions.
21 changes: 8 additions & 13 deletions test/state/precompiles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -364,19 +364,14 @@ evmc::Result call_precompile(evmc_revision rev, const evmc_message& msg) noexcep
if (gas_left < 0)
return evmc::Result{EVMC_OUT_OF_GAS};

// Buffer for the precompile's output.
// Big enough to handle all "expmod" tests, but in case does not match the size requirement
// from analysis, the result will likely be incorrect.
// TODO: Replace with std::pmr::monotonic_buffer_resource?
uint8_t output_buf[4096];
assert(std::size(output_buf) >= max_output_size);

// Allocate buffer for the precompile's output and pass its ownership to evmc::Result.
// TODO: This can be done more elegantly by providing constructor evmc::Result(std::unique_ptr).
const auto output_data = new (std::nothrow) uint8_t[max_output_size];
const auto [status_code, output_size] =
execute(msg.input_data, msg.input_size, output_buf, std::size(output_buf));

evmc::Result result{
status_code, status_code == EVMC_SUCCESS ? gas_left : 0, 0, output_buf, output_size};

return result;
execute(msg.input_data, msg.input_size, output_data, max_output_size);
const evmc_result result{status_code, status_code == EVMC_SUCCESS ? gas_left : 0, 0,
output_data, output_size,
[](const evmc_result* res) noexcept { delete[] res->output_data; }};
return evmc::Result{result};
}
} // namespace evmone::state

0 comments on commit e186095

Please sign in to comment.