From 42494dd4cf3fd2bc3d54c733c49df32a2e9aa4e1 Mon Sep 17 00:00:00 2001 From: Olek <115580134+oleks-rip@users.noreply.github.com> Date: Wed, 21 Jan 2026 12:43:12 -0500 Subject: [PATCH] Ensure lifetime of imports (#6230) --- src/test/app/Wasm_test.cpp | 147 +++++++++++++------------- src/xrpld/app/wasm/WasmVM.h | 14 +-- src/xrpld/app/wasm/WasmiVM.h | 27 +++-- src/xrpld/app/wasm/detail/WasmVM.cpp | 32 +++--- src/xrpld/app/wasm/detail/WasmiVM.cpp | 62 ++++++----- 5 files changed, 143 insertions(+), 139 deletions(-) diff --git a/src/test/app/Wasm_test.cpp b/src/test/app/Wasm_test.cpp index 0eca654335..2ac0680422 100644 --- a/src/test/app/Wasm_test.cpp +++ b/src/test/app/Wasm_test.cpp @@ -84,9 +84,9 @@ struct Wasm_test : public beast::unit_test::suite // clang-format on auto& vm = WasmEngine::instance(); - ImportVec imports; + std::shared_ptr imports(std::make_shared()); WasmImpFunc( - imports, "func-add", reinterpret_cast(&Add)); + *imports, "func-add", reinterpret_cast(&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 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 hfs(new TestLedgerDataProvider(env)); + auto imports = std::make_shared(); + 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 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 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 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 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() gas - TestHostFunctions nfs(env, 0); - auto re = runEscrowWasm(wasm, nfs, ESCROW_FUNCTION_NAME, {}, -1); + std::shared_ptr 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 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 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 wasm(wasmStr.begin(), wasmStr.end()); - TestHostFunctionsSink nfs(env); + std::shared_ptr 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 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 hfs(new TestLedgerDataProvider(env)); + std::shared_ptr imports(std::make_shared()); 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 hfs(new TestLedgerDataProvider(env)); + std::shared_ptr imports(std::make_shared()); 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 hfs(new TestLedgerDataProvider(env)); + std::shared_ptr imports(std::make_shared()); 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 const wasm(wasmStr.begin(), wasmStr.end()); - TestHostFunctions hf(env, 0); - auto re = runEscrowWasm(wasm, hf, funcName, {}, 200'000); + std::shared_ptr 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 const wasm(wasmStr.begin(), wasmStr.end()); - TestHostFunctions hf(env, 0); - auto re = runEscrowWasm(wasm, hf, funcName, {}, 100'000); + std::shared_ptr 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 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 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 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 hfs(new TestLedgerDataProvider(env)); + std::shared_ptr imports(std::make_shared()); 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 hfs(new TestLedgerDataProvider(env)); - // ImportVec imports; + // std::shared_ptr imports(std::make_shared()); uint8_t buf1[8] = {7, 8, 9, 10, 11, 12, 13, 14}; { // forged "allocate" return valid address std::vector 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 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); } diff --git a/src/xrpld/app/wasm/WasmVM.h b/src/xrpld/app/wasm/WasmVM.h index c9c8d9c8e0..f14c475dc5 100644 --- a/src/xrpld/app/wasm/WasmVM.h +++ b/src/xrpld/app/wasm/WasmVM.h @@ -45,8 +45,8 @@ public: run(Bytes const& wasmCode, std::string_view funcName = {}, std::vector const& params = {}, - ImportVec const& imports = {}, - HostFunctions* hfs = nullptr, + std::shared_ptr const& imports = {}, + std::shared_ptr const& hfs = {}, int64_t gasLimit = -1, beast::Journal j = beast::Journal{beast::Journal::getNullSink()}); @@ -55,8 +55,8 @@ public: Bytes const& wasmCode, std::string_view funcName, std::vector const& params = {}, - ImportVec const& imports = {}, - HostFunctions* hfs = nullptr, + std::shared_ptr const& imports = {}, + std::shared_ptr const& hfs = {}, beast::Journal j = beast::Journal{beast::Journal::getNullSink()}); // Host functions helper functionality @@ -69,13 +69,13 @@ public: //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -ImportVec +std::shared_ptr createWasmImport(HostFunctions& hfs); Expected runEscrowWasm( Bytes const& wasmCode, - HostFunctions& hfs, + std::shared_ptr const& hfs, std::string_view funcName = ESCROW_FUNCTION_NAME, std::vector const& params = {}, int64_t gasLimit = -1); @@ -83,7 +83,7 @@ runEscrowWasm( NotTEC preflightEscrowWasm( Bytes const& wasmCode, - HostFunctions& hfs, + std::shared_ptr const& hfs, std::string_view funcName = ESCROW_FUNCTION_NAME, std::vector const& params = {}); diff --git a/src/xrpld/app/wasm/WasmiVM.h b/src/xrpld/app/wasm/WasmiVM.h index 0d051ea49b..d7e52d6a0e 100644 --- a/src/xrpld/app/wasm/WasmiVM.h +++ b/src/xrpld/app/wasm/WasmiVM.h @@ -172,7 +172,7 @@ public: StorePtr& s, Bytes const& wasmBin, bool instantiate, - ImportVec const& imports, + std::shared_ptr const& imports, beast::Journal j); ~ModuleWrapper() = default; @@ -198,7 +198,7 @@ public: private: WasmExternVec - buildImports(StorePtr& s, ImportVec const& imports); + buildImports(StorePtr& s, std::shared_ptr const& imports); }; class WasmiEngine @@ -210,6 +210,10 @@ class WasmiEngine std::mutex m_; // 1 instance mutex + // to ensure lifetime during next executions with the same module + std::shared_ptr imports_; + std::shared_ptr hfs_; + public: WasmiEngine(); ~WasmiEngine() = default; @@ -221,8 +225,8 @@ public: run(Bytes const& wasmCode, std::string_view funcName, std::vector const& params, - ImportVec const& imports, - HostFunctions* hfs, + std::shared_ptr const& imports, + std::shared_ptr const& hfs, int64_t gas, beast::Journal j); @@ -231,8 +235,8 @@ public: Bytes const& wasmCode, std::string_view funcName, std::vector const& params, - ImportVec const& imports, - HostFunctions* hfs, + std::shared_ptr const& imports, + std::shared_ptr const& hfs, beast::Journal j); std::int64_t @@ -260,23 +264,16 @@ private: Bytes const& wasmCode, std::string_view funcName, std::vector const& params, - ImportVec const& imports, - HostFunctions* hfs, int64_t gas); NotTEC checkHlp( Bytes const& wasmCode, std::string_view funcName, - std::vector const& params, - ImportVec const& imports); + std::vector const& params); int - addModule( - Bytes const& wasmCode, - bool instantiate, - int64_t gas, - ImportVec const& imports); + addModule(Bytes const& wasmCode, bool instantiate, int64_t gas); void clearModules(); diff --git a/src/xrpld/app/wasm/detail/WasmVM.cpp b/src/xrpld/app/wasm/detail/WasmVM.cpp index 062e50ba93..c7fa3bbb5b 100644 --- a/src/xrpld/app/wasm/detail/WasmVM.cpp +++ b/src/xrpld/app/wasm/detail/WasmVM.cpp @@ -89,13 +89,13 @@ setCommonHostFunctions(HostFunctions* hfs, ImportVec& i) // clang-format on } -ImportVec +std::shared_ptr createWasmImport(HostFunctions& hfs) { - ImportVec i; + std::shared_ptr i(std::make_shared()); - setCommonHostFunctions(&hfs, i); - WASM_IMPORT_FUNC2(i, updateData, "update_data", &hfs, 1000); + setCommonHostFunctions(&hfs, *i); + WASM_IMPORT_FUNC2(*i, updateData, "update_data", &hfs, 1000); return i; } @@ -103,7 +103,7 @@ createWasmImport(HostFunctions& hfs) Expected runEscrowWasm( Bytes const& wasmCode, - HostFunctions& hfs, + std::shared_ptr const& hfs, std::string_view funcName, std::vector const& params, int64_t gasLimit) @@ -116,10 +116,10 @@ runEscrowWasm( wasmCode, funcName, params, - createWasmImport(hfs), - &hfs, + createWasmImport(*hfs), + hfs, gasLimit, - hfs.getJournal()); + hfs->getJournal()); // std::cout << "runEscrowWasm, mod size: " << wasmCode.size() // << ", gasLimit: " << gasLimit << ", funcName: " << funcName; @@ -142,7 +142,7 @@ runEscrowWasm( NotTEC preflightEscrowWasm( Bytes const& wasmCode, - HostFunctions& hfs, + std::shared_ptr const& hfs, std::string_view funcName, std::vector const& params) { @@ -154,9 +154,9 @@ preflightEscrowWasm( wasmCode, funcName, params, - createWasmImport(hfs), - &hfs, - hfs.getJournal()); + createWasmImport(*hfs), + hfs, + hfs->getJournal()); return ret; } @@ -179,8 +179,8 @@ WasmEngine::run( Bytes const& wasmCode, std::string_view funcName, std::vector const& params, - ImportVec const& imports, - HostFunctions* hfs, + std::shared_ptr const& imports, + std::shared_ptr const& hfs, int64_t gasLimit, beast::Journal j) { @@ -192,8 +192,8 @@ WasmEngine::check( Bytes const& wasmCode, std::string_view funcName, std::vector const& params, - ImportVec const& imports, - HostFunctions* hfs, + std::shared_ptr const& imports, + std::shared_ptr const& hfs, beast::Journal j) { return impl->check(wasmCode, funcName, params, imports, hfs, j); diff --git a/src/xrpld/app/wasm/detail/WasmiVM.cpp b/src/xrpld/app/wasm/detail/WasmiVM.cpp index 8bd4a7b8b8..037f787a26 100644 --- a/src/xrpld/app/wasm/detail/WasmiVM.cpp +++ b/src/xrpld/app/wasm/detail/WasmiVM.cpp @@ -255,7 +255,7 @@ ModuleWrapper::ModuleWrapper( StorePtr& s, Bytes const& wasmBin, bool instantiate, - ImportVec const& imports, + std::shared_ptr const& imports, beast::Journal j) : module_(init(s, wasmBin, j)), j_(j) { @@ -342,13 +342,17 @@ makeImpReturn(WasmImportFunc const& imp) } WasmExternVec -ModuleWrapper::buildImports(StorePtr& s, ImportVec const& imports) +ModuleWrapper::buildImports( + StorePtr& s, + std::shared_ptr const& imports) { WasmImporttypeVec importTypes; wasm_module_imports(module_.get(), &importTypes.vec_); if (!importTypes.vec_.size) return {}; + if (!imports) + throw std::runtime_error("Missing imports"); WasmExternVec wimports(importTypes.vec_.size); @@ -374,7 +378,7 @@ ModuleWrapper::buildImports(StorePtr& s, ImportVec const& imports) // continue; bool impSet = false; - for (auto const& obj : imports) + for (auto const& obj : *imports) { auto const& imp = obj.second; if (imp.name != fieldName) @@ -536,11 +540,7 @@ WasmiEngine::WasmiEngine() } int -WasmiEngine::addModule( - Bytes const& wasmCode, - bool instantiate, - int64_t gas, - ImportVec const& imports) +WasmiEngine::addModule(Bytes const& wasmCode, bool instantiate, int64_t gas) { moduleWrap_.reset(); store_.reset(); // to free the memory before creating new store @@ -562,7 +562,7 @@ WasmiEngine::addModule( } moduleWrap_ = std::make_unique( - store_, wasmCode, instantiate, imports, j_); + store_, wasmCode, instantiate, imports_, j_); if (!moduleWrap_) throw std::runtime_error( @@ -800,16 +800,24 @@ WasmiEngine::run( Bytes const& wasmCode, std::string_view funcName, std::vector const& params, - ImportVec const& imports, - HostFunctions* hfs, + std::shared_ptr const& imports, + std::shared_ptr const& hfs, int64_t gas, beast::Journal j) { j_ = j; + + if (!wasmCode.empty()) + { // save values for reuse + imports_ = imports; + hfs_ = hfs; + } + try { - checkImports(imports, hfs); - return runHlp(wasmCode, funcName, params, imports, hfs, gas); + if (imports_) + checkImports(*imports_, hfs.get()); + return runHlp(wasmCode, funcName, params, gas); } catch (std::exception const& e) { @@ -829,8 +837,6 @@ WasmiEngine::runHlp( Bytes const& wasmCode, std::string_view funcName, std::vector const& params, - ImportVec const& imports, - HostFunctions* hfs, int64_t gas) { // currently only 1 module support, possible parallel UT run @@ -839,14 +845,14 @@ WasmiEngine::runHlp( // Create and instantiate the module. if (!wasmCode.empty()) { - [[maybe_unused]] int const m = addModule(wasmCode, true, gas, imports); + [[maybe_unused]] int const m = addModule(wasmCode, true, gas); } if (!moduleWrap_ || !moduleWrap_->instanceWrap_) throw std::runtime_error("no instance"); // LCOV_EXCL_LINE - if (hfs) - hfs->setRT(&getRT()); + if (hfs_) + hfs_->setRT(&getRT()); // Call main auto const f = getFunc(!funcName.empty() ? funcName : "_start"); @@ -890,16 +896,23 @@ WasmiEngine::check( Bytes const& wasmCode, std::string_view funcName, std::vector const& params, - ImportVec const& imports, - HostFunctions* hfs, + std::shared_ptr const& imports, + std::shared_ptr const& hfs, beast::Journal j) { j_ = j; + if (!wasmCode.empty()) + { + imports_ = imports; + hfs_ = hfs; + } + try { - checkImports(imports, hfs); - return checkHlp(wasmCode, funcName, params, imports); + if (imports_) + checkImports(*imports_, hfs_.get()); + return checkHlp(wasmCode, funcName, params); } catch (std::exception const& e) { @@ -919,8 +932,7 @@ NotTEC WasmiEngine::checkHlp( Bytes const& wasmCode, std::string_view funcName, - std::vector const& params, - ImportVec const& imports) + std::vector const& params) { // currently only 1 module support, possible parallel UT run std::lock_guard lg(m_); @@ -929,7 +941,7 @@ WasmiEngine::checkHlp( if (wasmCode.empty()) throw std::runtime_error("empty nodule"); - int const m = addModule(wasmCode, false, -1, imports); + int const m = addModule(wasmCode, false, -1); if ((m < 0) || !moduleWrap_) throw std::runtime_error("no module"); // LCOV_EXCL_LINE