Skip to content

Commit b7bee06

Browse files
authored
precompiles: Improve output buffer handling (#951)
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.
1 parent 70ca837 commit b7bee06

File tree

1 file changed

+8
-13
lines changed

1 file changed

+8
-13
lines changed

test/state/precompiles.cpp

+8-13
Original file line numberDiff line numberDiff line change
@@ -364,19 +364,14 @@ evmc::Result call_precompile(evmc_revision rev, const evmc_message& msg) noexcep
364364
if (gas_left < 0)
365365
return evmc::Result{EVMC_OUT_OF_GAS};
366366

367-
// Buffer for the precompile's output.
368-
// Big enough to handle all "expmod" tests, but in case does not match the size requirement
369-
// from analysis, the result will likely be incorrect.
370-
// TODO: Replace with std::pmr::monotonic_buffer_resource?
371-
uint8_t output_buf[4096];
372-
assert(std::size(output_buf) >= max_output_size);
373-
367+
// Allocate buffer for the precompile's output and pass its ownership to evmc::Result.
368+
// TODO: This can be done more elegantly by providing constructor evmc::Result(std::unique_ptr).
369+
const auto output_data = new (std::nothrow) uint8_t[max_output_size];
374370
const auto [status_code, output_size] =
375-
execute(msg.input_data, msg.input_size, output_buf, std::size(output_buf));
376-
377-
evmc::Result result{
378-
status_code, status_code == EVMC_SUCCESS ? gas_left : 0, 0, output_buf, output_size};
379-
380-
return result;
371+
execute(msg.input_data, msg.input_size, output_data, max_output_size);
372+
const evmc_result result{status_code, status_code == EVMC_SUCCESS ? gas_left : 0, 0,
373+
output_data, output_size,
374+
[](const evmc_result* res) noexcept { delete[] res->output_data; }};
375+
return evmc::Result{result};
381376
}
382377
} // namespace evmone::state

0 commit comments

Comments
 (0)