Fix for Big-Endian machines (#6245)

This commit is contained in:
Olek
2026-01-27 13:05:54 -05:00
committed by GitHub
parent 917c610f96
commit f1f2e2629f
4 changed files with 118 additions and 13 deletions

View File

@@ -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();
}

View File

@@ -261,4 +261,35 @@ wasmParams(Types&&... args)
return v;
}
template <typename T, size_t size = sizeof(T)>
inline constexpr T
adjustWasmEndianessHlp(T x)
{
static_assert(std::is_integral<T>::value, "Only integral types");
if constexpr (size > 1)
{
using U = std::make_unsigned<T>::type;
U u = static_cast<U>(x);
U const low = (u & 0xFF) << ((size - 1) << 3);
u = adjustWasmEndianessHlp<U, size - 1>(u >> 8);
return static_cast<T>(low | u);
}
return x;
}
template <typename T, size_t size = sizeof(T)>
inline constexpr T
adjustWasmEndianess(T x)
{
// LCOV_EXCL_START
static_assert(std::is_integral<T>::value, "Only integral types");
if constexpr (std::endian::native == std::endian::big)
{
return adjustWasmEndianessHlp(x);
}
return x;
// LCOV_EXCL_STOP
}
} // namespace xrpl

View File

@@ -9,6 +9,19 @@ typedef std::variant<STBase const*, uint256 const*> FieldValue;
namespace detail {
template <class T>
Bytes
getIntBytes(STBase const* obj)
{
static_assert(std::is_integral<T>::value, "Only integral types");
auto const& num(static_cast<STInteger<T> const*>(obj));
T const data = adjustWasmEndianess(num->value());
auto const* b = reinterpret_cast<uint8_t const*>(&data);
auto const* e = reinterpret_cast<uint8_t const*>(&data + 1);
return Bytes{b, e};
}
static Expected<Bytes, HostFunctionError>
getAnyFieldData(STBase const* obj)
{
@@ -58,20 +71,25 @@ getAnyFieldData(STBase const* obj)
}
break;
case STI_UINT16: {
auto const& num(static_cast<STInteger<std::uint16_t> const*>(obj));
std::uint16_t const data = num->value();
auto const* b = reinterpret_cast<uint8_t const*>(&data);
auto const* e = reinterpret_cast<uint8_t const*>(&data + 1);
return Bytes{b, e};
return getIntBytes<std::uint16_t>(obj);
}
break;
case STI_UINT32: {
auto const* num(static_cast<STInteger<std::uint32_t> const*>(obj));
std::uint32_t const data = num->value();
auto const* b = reinterpret_cast<uint8_t const*>(&data);
auto const* e = reinterpret_cast<uint8_t const*>(&data + 1);
return Bytes{b, e};
return getIntBytes<std::uint32_t>(obj);
}
// LCOV_EXCL_START
case STI_UINT64: {
return getIntBytes<std::uint64_t>(obj);
}
break;
case STI_INT32: {
return getIntBytes<std::int32_t>(obj);
}
break;
case STI_INT64: {
return getIntBytes<std::int64_t>(obj);
}
// LCOV_EXCL_STOP
break;
case STI_UINT256: {
auto const* uint256Obj(static_cast<STUInt256 const*>(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())
{

View File

@@ -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<uint64_t const*>(r->data());
x = adjustWasmEndianess(x);
return x;
}
@@ -290,7 +291,7 @@ returnResult(
}
else if constexpr (std::is_same_v<t, std::uint32_t>)
{
auto const resultValue = res.value();
auto const resultValue = adjustWasmEndianess(res.value());
return hfResult(
results,
setData(