Ensure lifetime of imports (#6230)

This commit is contained in:
Olek
2026-01-21 12:43:12 -05:00
committed by GitHub
parent ce84cc8b44
commit 42494dd4cf
5 changed files with 143 additions and 139 deletions

View File

@@ -84,9 +84,9 @@ struct Wasm_test : public beast::unit_test::suite
// clang-format on
auto& vm = WasmEngine::instance();
ImportVec imports;
std::shared_ptr<ImportVec> imports(std::make_shared<ImportVec>());
WasmImpFunc<Add_proto>(
imports, "func-add", reinterpret_cast<void*>(&Add));
*imports, "func-add", reinterpret_cast<void*>(&Add));
auto re = vm.run(wasm, "addTwo", wasmParams(1234, 5678), imports);
@@ -107,7 +107,7 @@ struct Wasm_test : public beast::unit_test::suite
using namespace test::jtx;
Env env{*this};
HostFunctions hfs(env.journal);
std::shared_ptr<HostFunctions> hfs(new HostFunctions(env.journal));
{
auto wasmHex = "00000000";
@@ -165,10 +165,10 @@ struct Wasm_test : public beast::unit_test::suite
using namespace test::jtx;
Env env{*this};
TestLedgerDataProvider hf(env);
ImportVec imports;
WASM_IMPORT_FUNC2(imports, getLedgerSqn, "get_ledger_sqn", &hf, 33);
std::shared_ptr<HostFunctions> hfs(new TestLedgerDataProvider(env));
auto imports = std::make_shared<ImportVec>();
WASM_IMPORT_FUNC2(
*imports, getLedgerSqn, "get_ledger_sqn", hfs.get(), 33);
auto& engine = WasmEngine::instance();
auto re = engine.run(
@@ -176,7 +176,7 @@ struct Wasm_test : public beast::unit_test::suite
ESCROW_FUNCTION_NAME,
{},
imports,
&hf,
hfs,
1'000'000,
env.journal);
@@ -191,7 +191,7 @@ struct Wasm_test : public beast::unit_test::suite
// empty module - run the same instance
re = engine.run(
{}, ESCROW_FUNCTION_NAME, {}, imports, &hf, 1'000'000, env.journal);
{}, ESCROW_FUNCTION_NAME, {}, imports, hfs, 1'000'000, env.journal);
if (BEAST_EXPECT(re.has_value()))
{
@@ -277,9 +277,9 @@ struct Wasm_test : public beast::unit_test::suite
auto& engine = WasmEngine::instance();
TestHostFunctions hfs(env, 0);
ImportVec imp = createWasmImport(hfs);
for (auto& i : imp)
std::shared_ptr<HostFunctions> hfs(new TestHostFunctions(env, 0));
auto imp = createWasmImport(*hfs);
for (auto& i : *imp)
i.second.gas = 0;
auto re = engine.run(
@@ -287,7 +287,7 @@ struct Wasm_test : public beast::unit_test::suite
ESCROW_FUNCTION_NAME,
{},
imp,
&hfs,
hfs,
1'000'000,
env.journal);
@@ -313,15 +313,15 @@ struct Wasm_test : public beast::unit_test::suite
auto& engine = WasmEngine::instance();
TestHostFunctions hfs(env, 0);
ImportVec const imp = createWasmImport(hfs);
std::shared_ptr<HostFunctions> hfs(new TestHostFunctions(env, 0));
auto const imp = createWasmImport(*hfs);
auto re = engine.run(
wasm,
ESCROW_FUNCTION_NAME,
{},
imp,
&hfs,
hfs,
1'000'000,
env.journal);
@@ -342,11 +342,11 @@ struct Wasm_test : public beast::unit_test::suite
auto& engine = WasmEngine::instance();
TestHostFunctions hfs(env, 0);
ImportVec const imp = createWasmImport(hfs);
std::shared_ptr<HostFunctions> hfs(new TestHostFunctions(env, 0));
auto const imp = createWasmImport(*hfs);
auto re = engine.run(
wasm, ESCROW_FUNCTION_NAME, {}, imp, &hfs, 200, env.journal);
wasm, ESCROW_FUNCTION_NAME, {}, imp, hfs, 200, env.journal);
if (BEAST_EXPECT(!re))
{
@@ -371,9 +371,9 @@ struct Wasm_test : public beast::unit_test::suite
using namespace test::jtx;
Env env{*this};
{
TestHostFunctions nfs(env, 0);
std::shared_ptr<HostFunctions> hfs(new TestHostFunctions(env, 0));
auto re =
runEscrowWasm(wasm, nfs, ESCROW_FUNCTION_NAME, {}, 100'000);
runEscrowWasm(wasm, hfs, ESCROW_FUNCTION_NAME, {}, 100'000);
if (BEAST_EXPECT(re.has_value()))
{
BEAST_EXPECTS(re->result == 1, std::to_string(re->result));
@@ -383,8 +383,8 @@ struct Wasm_test : public beast::unit_test::suite
{
// max<int64_t>() gas
TestHostFunctions nfs(env, 0);
auto re = runEscrowWasm(wasm, nfs, ESCROW_FUNCTION_NAME, {}, -1);
std::shared_ptr<HostFunctions> hfs(new TestHostFunctions(env, 0));
auto re = runEscrowWasm(wasm, hfs, ESCROW_FUNCTION_NAME, {}, -1);
if (BEAST_EXPECT(re.has_value()))
{
BEAST_EXPECTS(re->result == 1, std::to_string(re->result));
@@ -404,9 +404,10 @@ struct Wasm_test : public beast::unit_test::suite
return Unexpected(HostFunctionError::FIELD_NOT_FOUND);
}
};
BadTestHostFunctions nfs(env);
std::shared_ptr<HostFunctions> hfs(new BadTestHostFunctions(env));
auto re =
runEscrowWasm(wasm, nfs, ESCROW_FUNCTION_NAME, {}, 100'000);
runEscrowWasm(wasm, hfs, ESCROW_FUNCTION_NAME, {}, 100'000);
if (BEAST_EXPECT(re.has_value()))
{
BEAST_EXPECTS(re->result == -201, std::to_string(re->result));
@@ -426,9 +427,10 @@ struct Wasm_test : public beast::unit_test::suite
return Bytes((128 + 1) * 64 * 1024, 1);
}
};
BadTestHostFunctions nfs(env);
std::shared_ptr<HostFunctions> hfs(new BadTestHostFunctions(env));
auto re =
runEscrowWasm(wasm, nfs, ESCROW_FUNCTION_NAME, {}, 100'000);
runEscrowWasm(wasm, hfs, ESCROW_FUNCTION_NAME, {}, 100'000);
if (BEAST_EXPECT(re.has_value()))
{
BEAST_EXPECTS(re->result == -201, std::to_string(re->result));
@@ -441,14 +443,15 @@ struct Wasm_test : public beast::unit_test::suite
auto const wasmStr = boost::algorithm::unhex(deepRecursionHex);
std::vector<uint8_t> wasm(wasmStr.begin(), wasmStr.end());
TestHostFunctionsSink nfs(env);
std::shared_ptr<TestHostFunctionsSink> hfs(
new TestHostFunctionsSink(env));
std::string funcName("finish");
auto re = runEscrowWasm(wasm, nfs, funcName, {}, 1'000'000'000);
auto re = runEscrowWasm(wasm, hfs, funcName, {}, 1'000'000'000);
BEAST_EXPECT(!re && re.error());
// std::cout << "bad case (deep recursion) result " << re.error()
// << std::endl;
auto const& sink = nfs.getSink();
auto const& sink = hfs->getSink();
auto countSubstr = [](std::string const& str,
std::string const& substr) {
std::size_t pos = 0;
@@ -471,7 +474,7 @@ struct Wasm_test : public beast::unit_test::suite
auto const wasmStr = boost::algorithm::unhex(infiniteLoopWasmHex);
Bytes wasm(wasmStr.begin(), wasmStr.end());
std::string const funcName("loop");
TestHostFunctions hfs(env, 0);
std::shared_ptr<HostFunctions> hfs(new TestHostFunctions(env, 0));
// infinite loop should be caught and fail
auto const re = runEscrowWasm(wasm, hfs, funcName, {}, 1'000'000);
@@ -485,11 +488,10 @@ struct Wasm_test : public beast::unit_test::suite
// expected import not provided
auto wasmStr = boost::algorithm::unhex(ledgerSqnWasmHex);
Bytes wasm(wasmStr.begin(), wasmStr.end());
TestLedgerDataProvider ledgerDataProvider(env);
ImportVec imports;
std::shared_ptr<HostFunctions> hfs(new TestLedgerDataProvider(env));
std::shared_ptr<ImportVec> imports(std::make_shared<ImportVec>());
WASM_IMPORT_FUNC2(
imports, getLedgerSqn, "get_ledger_sqn2", &ledgerDataProvider);
*imports, getLedgerSqn, "get_ledger_sqn2", hfs.get());
auto& engine = WasmEngine::instance();
@@ -498,7 +500,7 @@ struct Wasm_test : public beast::unit_test::suite
ESCROW_FUNCTION_NAME,
{},
imports,
&ledgerDataProvider,
hfs,
1'000'000,
env.journal);
@@ -509,12 +511,11 @@ struct Wasm_test : public beast::unit_test::suite
// bad import format
auto wasmStr = boost::algorithm::unhex(ledgerSqnWasmHex);
Bytes wasm(wasmStr.begin(), wasmStr.end());
TestLedgerDataProvider ledgerDataProvider(env);
ImportVec imports;
std::shared_ptr<HostFunctions> hfs(new TestLedgerDataProvider(env));
std::shared_ptr<ImportVec> imports(std::make_shared<ImportVec>());
WASM_IMPORT_FUNC2(
imports, getLedgerSqn, "get_ledger_sqn", &ledgerDataProvider);
imports[0].first = nullptr;
*imports, getLedgerSqn, "get_ledger_sqn", hfs.get());
(*imports)[0].first = nullptr;
auto& engine = WasmEngine::instance();
@@ -523,7 +524,7 @@ struct Wasm_test : public beast::unit_test::suite
ESCROW_FUNCTION_NAME,
{},
imports,
&ledgerDataProvider,
hfs,
1'000'000,
env.journal);
@@ -534,21 +535,14 @@ struct Wasm_test : public beast::unit_test::suite
// bad function name
auto wasmStr = boost::algorithm::unhex(ledgerSqnWasmHex);
Bytes wasm(wasmStr.begin(), wasmStr.end());
TestLedgerDataProvider ledgerDataProvider(env);
ImportVec imports;
std::shared_ptr<HostFunctions> hfs(new TestLedgerDataProvider(env));
std::shared_ptr<ImportVec> imports(std::make_shared<ImportVec>());
WASM_IMPORT_FUNC2(
imports, getLedgerSqn, "get_ledger_sqn", &ledgerDataProvider);
*imports, getLedgerSqn, "get_ledger_sqn", hfs.get());
auto& engine = WasmEngine::instance();
auto re = engine.run(
wasm,
"func1",
{},
imports,
&ledgerDataProvider,
1'000'000,
env.journal);
wasm, "func1", {}, imports, hfs, 1'000'000, env.journal);
BEAST_EXPECT(!re);
}
@@ -569,8 +563,8 @@ struct Wasm_test : public beast::unit_test::suite
std::string const wasmStr = boost::algorithm::unhex(wasmHex);
std::vector<uint8_t> const wasm(wasmStr.begin(), wasmStr.end());
TestHostFunctions hf(env, 0);
auto re = runEscrowWasm(wasm, hf, funcName, {}, 200'000);
std::shared_ptr<HostFunctions> hfs(new TestHostFunctions(env, 0));
auto re = runEscrowWasm(wasm, hfs, funcName, {}, 200'000);
if (BEAST_EXPECT(re.has_value()))
{
BEAST_EXPECTS(re->result == 1, std::to_string(re->result));
@@ -584,8 +578,8 @@ struct Wasm_test : public beast::unit_test::suite
std::string const wasmStr = boost::algorithm::unhex(wasmHex);
std::vector<uint8_t> const wasm(wasmStr.begin(), wasmStr.end());
TestHostFunctions hf(env, 0);
auto re = runEscrowWasm(wasm, hf, funcName, {}, 100'000);
std::shared_ptr<HostFunctions> hfs(new TestHostFunctions(env, 0));
auto re = runEscrowWasm(wasm, hfs, funcName, {}, 100'000);
if (BEAST_EXPECT(re.has_value()))
{
BEAST_EXPECTS(re->result == 1, std::to_string(re->result));
@@ -671,9 +665,10 @@ struct Wasm_test : public beast::unit_test::suite
env(token::mint(alan, 0u));
env.close();
PerfHostFunctions nfs(env, k, env.tx());
std::shared_ptr<HostFunctions> hfs(
new PerfHostFunctions(env, k, env.tx()));
auto re = runEscrowWasm(wasm, nfs, ESCROW_FUNCTION_NAME);
auto re = runEscrowWasm(wasm, hfs, ESCROW_FUNCTION_NAME);
if (BEAST_EXPECT(re.has_value()))
{
BEAST_EXPECT(re->result);
@@ -701,7 +696,7 @@ struct Wasm_test : public beast::unit_test::suite
auto const wasmStr = boost::algorithm::unhex(codecovTestsWasmHex);
Bytes const wasm(wasmStr.begin(), wasmStr.end());
TestHostFunctions hfs(env, 0);
std::shared_ptr<HostFunctions> hfs(new TestHostFunctions(env, 0));
auto const allowance = 185'974;
auto re = runEscrowWasm(wasm, hfs, ESCROW_FUNCTION_NAME, {}, allowance);
@@ -724,7 +719,7 @@ struct Wasm_test : public beast::unit_test::suite
auto const wasmStr = boost::algorithm::unhex(disabledFloatHex);
Bytes wasm(wasmStr.begin(), wasmStr.end());
std::string const funcName("finish");
TestHostFunctions hfs(env, 0);
std::shared_ptr<HostFunctions> hfs(new TestHostFunctions(env, 0));
{
// f32 set constant, opcode disabled exception
@@ -868,12 +863,12 @@ struct Wasm_test : public beast::unit_test::suite
auto wasmStr = boost::algorithm::unhex(startLoopHex);
Bytes wasm(wasmStr.begin(), wasmStr.end());
TestLedgerDataProvider ledgerDataProvider(env);
ImportVec imports;
std::shared_ptr<HostFunctions> hfs(new TestLedgerDataProvider(env));
std::shared_ptr<ImportVec> imports(std::make_shared<ImportVec>());
auto& engine = WasmEngine::instance();
auto checkRes = engine.check(
wasm, "finish", {}, imports, &ledgerDataProvider, env.journal);
auto checkRes =
engine.check(wasm, "finish", {}, imports, hfs, env.journal);
BEAST_EXPECTS(
checkRes == tesSUCCESS, std::to_string(TERtoInt(checkRes)));
@@ -882,7 +877,7 @@ struct Wasm_test : public beast::unit_test::suite
ESCROW_FUNCTION_NAME,
{},
imports,
&ledgerDataProvider,
hfs,
1'000'000,
env.journal);
BEAST_EXPECTS(
@@ -902,9 +897,9 @@ struct Wasm_test : public beast::unit_test::suite
using namespace test::jtx;
Env env{*this};
TestLedgerDataProvider hf(env);
std::shared_ptr<HostFunctions> hfs(new TestLedgerDataProvider(env));
// ImportVec imports;
// std::shared_ptr<ImportVec> imports(std::make_shared<ImportVec>());
uint8_t buf1[8] = {7, 8, 9, 10, 11, 12, 13, 14};
{ // forged "allocate" return valid address
std::vector<WasmParam> params = {
@@ -913,7 +908,7 @@ struct Wasm_test : public beast::unit_test::suite
auto& engine = WasmEngine::instance();
auto re = engine.run(
wasm, "test", params, {}, &hf, 1'000'000, env.journal);
wasm, "test", params, {}, hfs, 1'000'000, env.journal);
if (BEAST_EXPECT(re))
{
BEAST_EXPECTS(re->result == 7, std::to_string(re->result));
@@ -926,7 +921,7 @@ struct Wasm_test : public beast::unit_test::suite
{.type = WT_U8V, .of = {.u8v = {.d = buf1, .sz = 0}}}};
auto& engine = WasmEngine::instance();
auto re = engine.run(
wasm, "test", params, {}, &hf, 1'000'000, env.journal);
wasm, "test", params, {}, hfs, 1'000'000, env.journal);
BEAST_EXPECT(!re) &&
BEAST_EXPECT(re.error() == tecFAILED_PROCESSING);
}
@@ -936,7 +931,7 @@ struct Wasm_test : public beast::unit_test::suite
{.type = WT_U8V, .of = {.u8v = {.d = buf1, .sz = 1}}}};
auto& engine = WasmEngine::instance();
auto re = engine.run(
wasm, "test", params, {}, &hf, 1'000'000, env.journal);
wasm, "test", params, {}, hfs, 1'000'000, env.journal);
BEAST_EXPECT(!re) &&
BEAST_EXPECT(re.error() == tecFAILED_PROCESSING);
}
@@ -946,7 +941,7 @@ struct Wasm_test : public beast::unit_test::suite
{.type = WT_U8V, .of = {.u8v = {.d = buf1, .sz = 2}}}};
auto& engine = WasmEngine::instance();
auto re = engine.run(
wasm, "test", params, {}, &hf, 1'000'000, env.journal);
wasm, "test", params, {}, hfs, 1'000'000, env.journal);
BEAST_EXPECT(!re) &&
BEAST_EXPECT(re.error() == tecFAILED_PROCESSING);
}
@@ -956,7 +951,7 @@ struct Wasm_test : public beast::unit_test::suite
{.type = WT_U8V, .of = {.u8v = {.d = buf1, .sz = 3}}}};
auto& engine = WasmEngine::instance();
auto re = engine.run(
wasm, "test", params, {}, &hf, 1'000'000, env.journal);
wasm, "test", params, {}, hfs, 1'000'000, env.journal);
BEAST_EXPECT(!re) &&
BEAST_EXPECT(re.error() == tecFAILED_PROCESSING);
@@ -977,15 +972,15 @@ struct Wasm_test : public beast::unit_test::suite
using namespace test::jtx;
Env env{*this};
TestHostFunctions hf(env);
ImportVec imports = createWasmImport(hf);
std::shared_ptr<HostFunctions> hfs(new TestHostFunctions(env, 0));
auto imports = createWasmImport(*hfs);
{ // Calls float_from_uint with bad aligment.
// Can be checked through codecov
auto& engine = WasmEngine::instance();
auto re = engine.run(
wasm, "test", {}, imports, &hf, 1'000'000, env.journal);
wasm, "test", {}, imports, hfs, 1'000'000, env.journal);
BEAST_EXPECT(re && re->result == 0xbab88d46);
}