-
Notifications
You must be signed in to change notification settings - Fork 1.7k
feat: Read version information in Wasm Module #7805
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: ripple/smart-escrow
Are you sure you want to change the base?
Changes from 15 commits
730061f
72b9918
6082e0d
1556bb7
92ff416
a8d2004
dca957e
45f674d
f16fc10
8403958
d5c5fed
0b37247
b00e517
1d6829b
040e31d
b44a7c7
b05e127
025e25e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -21,6 +21,7 @@ | |||||
| #include <limits> | ||||||
| #include <memory> | ||||||
| #include <mutex> | ||||||
| #include <span> | ||||||
| #include <stdexcept> | ||||||
| #include <string> | ||||||
| #include <string_view> | ||||||
|
|
@@ -277,7 +278,7 @@ InstanceWrapper::setGas(std::int64_t gas) const | |||||
| ModulePtr | ||||||
| ModuleWrapper::init(StorePtr& s, Bytes const& wasmBin, beast::Journal j) | ||||||
| { | ||||||
| wasm_byte_vec_t const code{wasmBin.size(), (char*)(wasmBin.data())}; | ||||||
| wasm_byte_vec_t const code{.size = wasmBin.size(), .data = (char*)(wasmBin.data())}; | ||||||
| ModulePtr m = ModulePtr(wasm_module_new(s.get(), &code), &wasm_module_delete); | ||||||
| if (!m) | ||||||
| throw std::runtime_error("can't create module"); | ||||||
|
|
@@ -711,8 +712,8 @@ WasmiResult | |||||
| WasmiEngine::call(FuncInfo const& f, std::vector<wasm_val_t>& in) | ||||||
| { | ||||||
| WasmiResult ret(NR); | ||||||
| wasm_val_vec_t const inv = | ||||||
| in.empty() ? wasm_val_vec_t WASM_EMPTY_VEC : wasm_val_vec_t{in.size(), in.data()}; | ||||||
| wasm_val_vec_t const inv = in.empty() ? wasm_val_vec_t WASM_EMPTY_VEC | ||||||
| : wasm_val_vec_t{.size = in.size(), .data = in.data()}; | ||||||
|
|
||||||
| #ifdef SHOW_CALL_TIME | ||||||
| auto const start = usecs(); | ||||||
|
|
@@ -799,6 +800,134 @@ WasmiEngine::run( | |||||
| return Unexpected<TER>(tecFAILED_PROCESSING); | ||||||
| } | ||||||
|
|
||||||
| namespace { | ||||||
|
|
||||||
| struct CustomSection | ||||||
| { | ||||||
| std::string_view name; | ||||||
| std::span<char const> payload; | ||||||
| }; | ||||||
|
|
||||||
| struct Version | ||||||
| { | ||||||
| std::string_view name; | ||||||
| std::string_view version; | ||||||
|
|
||||||
| Version(std::string_view theName, std::string_view theVersion) | ||||||
| : name{theName}, version{theVersion} | ||||||
| { | ||||||
| } | ||||||
| }; | ||||||
|
|
||||||
| uint32_t | ||||||
| readLEB128(Bytes const& wasmCode, size_t& offset) | ||||||
| { | ||||||
| auto result = uint32_t{}; | ||||||
| auto shift = uint32_t{}; | ||||||
| while (offset < wasmCode.size()) | ||||||
| { | ||||||
| auto byte = wasmCode[offset++]; | ||||||
|
depthfirst-app[bot] marked this conversation as resolved.
|
||||||
| result |= static_cast<uint32_t>(byte & (shift < 28 ? 0x7Fu : 0x0Fu)) << shift; | ||||||
| if ((byte & 0x80) == 0) | ||||||
| { | ||||||
| break; | ||||||
| } | ||||||
| shift += 7; | ||||||
| if (shift >= 32) | ||||||
| { | ||||||
| // Drain the rest of the bytes for this leb. | ||||||
| while (offset < wasmCode.size()) | ||||||
| { | ||||||
| if ((wasmCode[offset++] & 0x80) == 0) | ||||||
| { | ||||||
| break; | ||||||
| } | ||||||
| } | ||||||
| break; | ||||||
|
TimothyBanks marked this conversation as resolved.
|
||||||
| } | ||||||
| } | ||||||
| return result; | ||||||
| } | ||||||
|
|
||||||
| template <typename Filter> | ||||||
| void | ||||||
| filterCustomSections(Bytes const& wasmCode, Filter&& filter) | ||||||
| { | ||||||
| auto offset = size_t{8}; // Skip Magic number and Version | ||||||
|
|
||||||
| if (wasmCode.size() <= offset) | ||||||
| { | ||||||
| // There is nothing to parse. | ||||||
| return; | ||||||
| } | ||||||
|
|
||||||
| while (offset < wasmCode.size()) | ||||||
| { | ||||||
| auto sectionId = wasmCode[offset++]; | ||||||
| auto sectionSize = readLEB128(wasmCode, offset); | ||||||
| auto nextSection = offset + sectionSize; | ||||||
|
depthfirst-app[bot] marked this conversation as resolved.
|
||||||
|
|
||||||
| if (nextSection > wasmCode.size()) | ||||||
| { | ||||||
| break; | ||||||
| } | ||||||
|
|
||||||
| if (sectionId == 0) | ||||||
| { | ||||||
| // Wasm custom section marker. | ||||||
| auto customSection = CustomSection{}; | ||||||
| auto size = readLEB128(wasmCode, offset); | ||||||
|
|
||||||
| if (offset + size > wasmCode.size() || offset + size > nextSection) | ||||||
| { | ||||||
| return; | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Malformed section causes early abort, skipping version info. Skip only this section and continue:
Suggested change
|
||||||
| } | ||||||
|
|
||||||
| customSection.name = | ||||||
| std::string_view{reinterpret_cast<char const*>(wasmCode.data()) + offset, size}; | ||||||
|
depthfirst-app[bot] marked this conversation as resolved.
|
||||||
| offset += size; | ||||||
|
|
||||||
| if (offset >= nextSection) | ||||||
| { | ||||||
| offset = nextSection; | ||||||
| continue; | ||||||
| } | ||||||
|
|
||||||
| size = nextSection - offset; | ||||||
| customSection.payload = std::span<char const>{ | ||||||
| reinterpret_cast<char const*>(wasmCode.data()) + offset, size}; | ||||||
|
|
||||||
| if (filter(customSection)) | ||||||
| { | ||||||
| return; | ||||||
| } | ||||||
| } | ||||||
| offset = nextSection; | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| std::vector<Version> | ||||||
| extractVersionInfo(Bytes const& wasmCode) | ||||||
| { | ||||||
| static constexpr auto kCommonLib = "xrpl-common-stdlib-version"; | ||||||
| static constexpr auto kEscrowLib = "xrpl-escrow-stdlib-version"; | ||||||
|
|
||||||
| auto versions = std::vector<Version>{}; | ||||||
| filterCustomSections(wasmCode, [&](auto const& section) { | ||||||
| if (section.name == kCommonLib || section.name == kEscrowLib) | ||||||
| { | ||||||
| versions.emplace_back( | ||||||
| section.name, std::string_view{section.payload.data(), section.payload.size()}); | ||||||
| } | ||||||
|
|
||||||
| // Just read until we have found all the information we are looking for. | ||||||
| return versions.size() == 2; | ||||||
| }); | ||||||
| return versions; | ||||||
| } | ||||||
|
|
||||||
| } // namespace | ||||||
|
|
||||||
| Expected<WasmResult<int32_t>, TER> | ||||||
| WasmiEngine::runHlp( | ||||||
| Bytes const& wasmCode, | ||||||
|
|
@@ -818,6 +947,11 @@ WasmiEngine::runHlp( | |||||
| if (!hfs.checkSelf()) | ||||||
| throw std::runtime_error("hfs isn't clean"); | ||||||
|
|
||||||
| for (auto const& version : extractVersionInfo(wasmCode)) | ||||||
| { | ||||||
| j_.debug() << "Module version: " << version.name << " " << version.version << "\n"; | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Redundant
Suggested change
|
||||||
| } | ||||||
|
|
||||||
| // Create and instantiate the module. | ||||||
| [[maybe_unused]] int const m = addModule(wasmCode, true, imports, gas); | ||||||
|
|
||||||
|
|
@@ -960,7 +1094,7 @@ wasm_trap_t* | |||||
| WasmiEngine::newTrap(std::string const& txt) | ||||||
| { | ||||||
| static char empty[1] = {0}; | ||||||
| wasm_message_t msg = {1, empty}; | ||||||
| wasm_message_t msg = {.size = 1, .data = empty}; | ||||||
|
|
||||||
| if (!txt.empty()) | ||||||
| wasm_name_new(&msg, txt.size() + 1, txt.c_str()); // include 0 | ||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| (module | ||
| ;; Define a table with exactly 0 entries | ||
| (table 0 funcref) | ||
|
|
||
| ;; Standard finish function | ||
| (func $finish (result i32) | ||
| i32.const 1 | ||
| ) | ||
| (export "finish" (func $finish)) | ||
|
|
||
| (@custom "xrpl-escrow-stdlib-version" "4.5.6") | ||
| (@custom "xrpl-common-stdlib-version" "1.2.3") | ||
| ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If git is not in PATH, subprocess.run raises FileNotFoundError. Wrap in try/except and fall back: