Merge pull request #257 from ethereum/cpp-host-call

cpp: Fix Host::call()
This commit is contained in:
Paweł Bylica 2019-04-29 16:38:42 +02:00 committed by GitHub
commit 2dc8eeb77c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 57 additions and 8 deletions

View File

@ -1,5 +1,13 @@
# Changelog
## [6.2.1] - unreleased
- Fixed:
[[#256](https://github.com/ethereum/evmc/issues/256),
[#257](https://github.com/ethereum/evmc/issues/257)]
Disallow implicit conversion from C++ `evmc::result` to `evmc_result`
causing unintendent premature releasing of resources.
## [6.2.0] - 2019-04-25
- Added: [[#216](https://github.com/ethereum/evmc/pull/216)]

View File

@ -66,12 +66,12 @@ jobs:
CXX: g++-8
CMAKE_OPTIONS: -DTOOLCHAIN=cxx17-pic
build-cxx14:
build-cxx14-asan:
<<: *build
environment:
CC: clang-8
CXX: clang++-8
CMAKE_OPTIONS: -DTOOLCHAIN=cxx14-pic
CMAKE_OPTIONS: -DTOOLCHAIN=cxx14-pic -DSANITIZE=address
build-gcc6:
<<: *build
@ -178,7 +178,7 @@ workflows:
jobs:
- lint
- build-cxx17
- build-cxx14
- build-cxx14-asan
- build-gcc6
- build-clang3.8
- bindings-go-latest

View File

@ -94,10 +94,14 @@ public:
evmc::result call(const evmc_message& msg) noexcept final
{
(void)msg;
// TODO: Improve C++ API for result creation.
evmc_result res{};
res.status_code = EVMC_FAILURE;
res.status_code = EVMC_REVERT;
auto output = new uint8_t[msg.input_size];
std::copy(&msg.input_data[0], &msg.input_data[msg.input_size], output);
res.output_size = msg.input_size;
res.output_data = output;
res.release = [](const evmc_result* r) noexcept { delete[] r->output_data; };
return evmc::result{res};
}

View File

@ -17,9 +17,15 @@ namespace evmc
///
/// This is a RAII wrapper for evmc_result and objects of this type
/// automatically release attached resources.
class result : public evmc_result
class result : private evmc_result
{
public:
using evmc_result::create_address;
using evmc_result::gas_left;
using evmc_result::output_data;
using evmc_result::output_size;
using evmc_result::status_code;
/// Converting constructor from raw evmc_result.
explicit result(evmc_result const& res) noexcept : evmc_result{res} {}
@ -45,6 +51,15 @@ public:
std::swap(*this, other);
return *this;
}
/// Returns the raw copy of evmc_result,
/// releases the ownership of the resources and invalidates this object.
evmc_result raw() noexcept
{
auto out = evmc_result{};
std::swap<evmc_result>(out, *this);
return out;
}
};
/// @copybrief evmc_instance
@ -302,7 +317,7 @@ inline void selfdestruct(evmc_context* h,
}
inline evmc_result call(evmc_context* h, const evmc_message* msg) noexcept
{
return static_cast<Host*>(h)->call(*msg);
return static_cast<Host*>(h)->call(*msg).raw();
}
inline evmc_tx_context get_tx_context(evmc_context* h) noexcept
{

View File

@ -87,7 +87,6 @@ TEST(cpp, host)
EXPECT_EQ(host.copy_code(a, 0, nullptr, 0), 0);
host.selfdestruct(a, a);
EXPECT_EQ(host.call({}).gas_left, 0);
auto tx = host.get_tx_context();
EXPECT_EQ(host.get_tx_context().block_number, tx.block_number);
@ -98,3 +97,26 @@ TEST(cpp, host)
example_host_destroy_context(host_context);
}
TEST(cpp, host_call)
{
// Use example host to test Host::call() method.
auto* host_context = example_host_create_context();
auto host = evmc::HostContext{host_context};
EXPECT_EQ(host.call({}).gas_left, 0);
auto msg = evmc_message{};
msg.gas = 1;
uint8_t input[] = {0xa, 0xb, 0xc};
msg.input_data = input;
msg.input_size = sizeof(input);
auto res = host.call(msg);
EXPECT_EQ(res.status_code, EVMC_REVERT);
EXPECT_EQ(res.output_size, msg.input_size);
EXPECT_TRUE(std::equal(&res.output_data[0], &res.output_data[res.output_size], msg.input_data));
example_host_destroy_context(host_context);
}