diff --git a/src/test/app/Wasm_test.cpp b/src/test/app/Wasm_test.cpp index b5e5d7fc73..a26328039b 100644 --- a/src/test/app/Wasm_test.cpp +++ b/src/test/app/Wasm_test.cpp @@ -1003,6 +1003,60 @@ struct Wasm_test : public beast::unit_test::suite } } + void + testSwapBytes() + { + testcase("Wasm swap bytes"); + + uint64_t const SWAP_DATAU64 = 0x123456789abcdeffull; + uint64_t const REVERSE_SWAP_DATAU64 = 0xffdebc9a78563412ull; + int64_t const SWAP_DATAI64 = 0x123456789abcdeffll; + int64_t const REVERSE_SWAP_DATAI64 = 0xffdebc9a78563412ll; + + uint32_t const SWAP_DATAU32 = 0x12789aff; + uint32_t const REVERSE_SWAP_DATAU32 = 0xff9a7812; + int32_t const SWAP_DATAI32 = 0x12789aff; + int32_t const REVERSE_SWAP_DATAI32 = 0xff9a7812; + + uint16_t const SWAP_DATAU16 = 0x12ff; + uint16_t const REVERSE_SWAP_DATAU16 = 0xff12; + int16_t const SWAP_DATAI16 = 0x12ff; + int16_t const REVERSE_SWAP_DATAI16 = 0xff12; + + uint64_t b1 = SWAP_DATAU64; + int64_t b2 = SWAP_DATAI64; + b1 = adjustWasmEndianessHlp(b1); + b2 = adjustWasmEndianessHlp(b2); + BEAST_EXPECT(b1 == REVERSE_SWAP_DATAU64); + BEAST_EXPECT(b2 == REVERSE_SWAP_DATAI64); + b1 = adjustWasmEndianessHlp(b1); + b2 = adjustWasmEndianessHlp(b2); + BEAST_EXPECT(b1 == SWAP_DATAU64); + BEAST_EXPECT(b2 == SWAP_DATAI64); + + uint32_t b3 = SWAP_DATAU32; + int32_t b4 = SWAP_DATAI32; + b3 = adjustWasmEndianessHlp(b3); + b4 = adjustWasmEndianessHlp(b4); + BEAST_EXPECT(b3 == REVERSE_SWAP_DATAU32); + BEAST_EXPECT(b4 == REVERSE_SWAP_DATAI32); + b3 = adjustWasmEndianessHlp(b3); + b4 = adjustWasmEndianessHlp(b4); + BEAST_EXPECT(b3 == SWAP_DATAU32); + BEAST_EXPECT(b4 == SWAP_DATAI32); + + uint16_t b5 = SWAP_DATAU16; + int16_t b6 = SWAP_DATAI16; + b5 = adjustWasmEndianessHlp(b5); + b6 = adjustWasmEndianessHlp(b6); + BEAST_EXPECT(b5 == REVERSE_SWAP_DATAU16); + BEAST_EXPECT(b6 == REVERSE_SWAP_DATAI16); + b5 = adjustWasmEndianessHlp(b5); + b6 = adjustWasmEndianessHlp(b6); + BEAST_EXPECT(b5 == SWAP_DATAU16); + BEAST_EXPECT(b6 == SWAP_DATAI16); + } + void run() override { @@ -1035,6 +1089,7 @@ struct Wasm_test : public beast::unit_test::suite testBadAlloc(); testBadAlign(); testReturnType(); + testSwapBytes(); // perfTest(); } diff --git a/src/xrpld/app/wasm/ParamsHelper.h b/src/xrpld/app/wasm/ParamsHelper.h index fb0b7f45dd..a7546ce092 100644 --- a/src/xrpld/app/wasm/ParamsHelper.h +++ b/src/xrpld/app/wasm/ParamsHelper.h @@ -261,4 +261,35 @@ wasmParams(Types&&... args) return v; } +template +inline constexpr T +adjustWasmEndianessHlp(T x) +{ + static_assert(std::is_integral::value, "Only integral types"); + if constexpr (size > 1) + { + using U = std::make_unsigned::type; + U u = static_cast(x); + U const low = (u & 0xFF) << ((size - 1) << 3); + u = adjustWasmEndianessHlp(u >> 8); + return static_cast(low | u); + } + + return x; +} + +template +inline constexpr T +adjustWasmEndianess(T x) +{ + // LCOV_EXCL_START + static_assert(std::is_integral::value, "Only integral types"); + if constexpr (std::endian::native == std::endian::big) + { + return adjustWasmEndianessHlp(x); + } + return x; + // LCOV_EXCL_STOP +} + } // namespace xrpl diff --git a/src/xrpld/app/wasm/detail/HostFuncImplGetter.cpp b/src/xrpld/app/wasm/detail/HostFuncImplGetter.cpp index 6b956de8a0..70fb1b5304 100644 --- a/src/xrpld/app/wasm/detail/HostFuncImplGetter.cpp +++ b/src/xrpld/app/wasm/detail/HostFuncImplGetter.cpp @@ -9,6 +9,19 @@ typedef std::variant FieldValue; namespace detail { +template +Bytes +getIntBytes(STBase const* obj) +{ + static_assert(std::is_integral::value, "Only integral types"); + + auto const& num(static_cast const*>(obj)); + T const data = adjustWasmEndianess(num->value()); + auto const* b = reinterpret_cast(&data); + auto const* e = reinterpret_cast(&data + 1); + return Bytes{b, e}; +} + static Expected getAnyFieldData(STBase const* obj) { @@ -58,20 +71,25 @@ getAnyFieldData(STBase const* obj) } break; case STI_UINT16: { - auto const& num(static_cast const*>(obj)); - std::uint16_t const data = num->value(); - auto const* b = reinterpret_cast(&data); - auto const* e = reinterpret_cast(&data + 1); - return Bytes{b, e}; + return getIntBytes(obj); } break; case STI_UINT32: { - auto const* num(static_cast const*>(obj)); - std::uint32_t const data = num->value(); - auto const* b = reinterpret_cast(&data); - auto const* e = reinterpret_cast(&data + 1); - return Bytes{b, e}; + return getIntBytes(obj); } + // LCOV_EXCL_START + case STI_UINT64: { + return getIntBytes(obj); + } + break; + case STI_INT32: { + return getIntBytes(obj); + } + break; + case STI_INT64: { + return getIntBytes(obj); + } + // LCOV_EXCL_STOP break; case STI_UINT256: { auto const* uint256Obj(static_cast(obj)); @@ -135,7 +153,7 @@ locateField(STObject const& obj, Slice const& locator) auto const& knownSFields = SField::getKnownCodeToField(); { - int32_t const sfieldCode = locPtr[0]; + int32_t const sfieldCode = adjustWasmEndianess(locPtr[0]); auto const it = knownSFields.find(sfieldCode); if (it == knownSFields.end()) return Unexpected(HostFunctionError::INVALID_FIELD); @@ -148,7 +166,7 @@ locateField(STObject const& obj, Slice const& locator) for (int i = 1; i < locSize; ++i) { - int32_t const sfieldCode = locPtr[i]; + int32_t const sfieldCode = adjustWasmEndianess(locPtr[i]); if (STI_ARRAY == field->getSType()) { diff --git a/src/xrpld/app/wasm/detail/HostFuncWrapper.cpp b/src/xrpld/app/wasm/detail/HostFuncWrapper.cpp index 8910f22aa1..da768ff6eb 100644 --- a/src/xrpld/app/wasm/detail/HostFuncWrapper.cpp +++ b/src/xrpld/app/wasm/detail/HostFuncWrapper.cpp @@ -77,6 +77,7 @@ getDataUInt64(IW const* runtime, wasm_val_vec_t const* params, int32_t& i) memcpy(&x, r->data(), sizeof(uint64_t)); else x = *reinterpret_cast(r->data()); + x = adjustWasmEndianess(x); return x; } @@ -290,7 +291,7 @@ returnResult( } else if constexpr (std::is_same_v) { - auto const resultValue = res.value(); + auto const resultValue = adjustWasmEndianess(res.value()); return hfResult( results, setData(