Fix unaligned access (#6208)

This commit is contained in:
Olek
2026-01-13 16:40:42 -05:00
committed by GitHub
parent 81cbc91927
commit c626b6403a
7 changed files with 105 additions and 3 deletions

View File

@@ -594,6 +594,24 @@ struct HostFuncImpl_test : public beast::unit_test::suite
}
}
{
// unaligned locator
std::vector<uint8_t> locatorVec(sizeof(int32_t) + 1);
memcpy(
locatorVec.data() + 1, &sfAccount.fieldCode, sizeof(int32_t));
Slice locator(
reinterpret_cast<uint8_t const*>(locatorVec.data() + 1),
sizeof(int32_t));
auto const account = hfs.getTxNestedField(locator);
if (BEAST_EXPECTS(
account.has_value(),
std::to_string(static_cast<int>(account.error()))))
{
BEAST_EXPECT(std::ranges::equal(*account, env.master.id()));
}
}
auto expectError = [&](std::vector<int32_t> const& locatorVec,
HostFunctionError expectedError) {
Slice locator(

View File

@@ -965,6 +965,33 @@ struct Wasm_test : public beast::unit_test::suite
env.close();
}
void
testBadAlign()
{
testcase("Wasm Bad Align");
// bad_align.c
auto wasmStr = boost::algorithm::unhex(badAlignHex);
Bytes wasm(wasmStr.begin(), wasmStr.end());
using namespace test::jtx;
Env env{*this};
TestHostFunctions hf(env);
ImportVec imports = createWasmImport(hf);
{ // 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);
BEAST_EXPECT(re && re->result == 0xbab88d46);
}
env.close();
}
void
run() override
{
@@ -995,6 +1022,7 @@ struct Wasm_test : public beast::unit_test::suite
testStartFunctionLoop();
testBadAlloc();
testBadAlign();
// perfTest();
}

View File

@@ -0,0 +1,23 @@
#include <stdint.h>
int32_t
float_from_uint(uint8_t const*, int32_t, uint8_t*, int32_t, int32_t);
int32_t
get_tx_nested_field(uint8_t const*, int32_t, uint8_t*, int32_t);
uint8_t e_data[32 * 1024];
int32_t
test()
{
e_data[1] = 0xFF;
e_data[2] = 0xFF;
e_data[3] = 0xFF;
e_data[4] = 0xFF;
e_data[5] = 0xFF;
e_data[6] = 0xFF;
e_data[7] = 0xFF;
e_data[8] = 0xFF;
float_from_uint(&e_data[1], 8, &e_data[35], 12, 0);
return *((int32_t*)(&e_data[36]));
}

View File

@@ -1378,3 +1378,20 @@ extern std::string const badAllocHex =
"3732302900490f7461726765745f6665617475726573042b0f6d757461626c652d676c6f62"
"616c732b087369676e2d6578742b0f7265666572656e63652d74797065732b0a6d756c7469"
"76616c7565";
extern std::string const badAlignHex =
"0061736d0100000001110360057f7f7f7f7f017f6000006000017f02170103656e760f666c"
"6f61745f66726f6d5f75696e7400000303020102050301000206400a7f004180080b7f0041"
"80080b7f00418088020b7f00418088020b7f00418088060b7f004180080b7f00418088060b"
"7f00418080080b7f0041000b7f0041010b07b1010d066d656d6f72790200115f5f7761736d"
"5f63616c6c5f63746f727300010474657374000206655f6461746103000c5f5f64736f5f68"
"616e646c6503010a5f5f646174615f656e6403020b5f5f737461636b5f6c6f7703030c5f5f"
"737461636b5f6869676803040d5f5f676c6f62616c5f6261736503050b5f5f686561705f62"
"61736503060a5f5f686561705f656e6403070d5f5f6d656d6f72795f6261736503080c5f5f"
"7461626c655f6261736503090a240202000b1f00418108427f370000418108410841a30841"
"0c410010001a41a4082802000b007f0970726f647563657273010c70726f6365737365642d"
"62790105636c616e675f31392e312e352d776173692d73646b202868747470733a2f2f6769"
"746875622e636f6d2f6c6c766d2f6c6c766d2d70726f6a6563742061623462356132646235"
"3832393538616631656533303861373930636664623432626432343732302900490f746172"
"6765745f6665617475726573042b0f6d757461626c652d676c6f62616c732b087369676e2d"
"6578742b0f7265666572656e63652d74797065732b0a6d756c746976616c7565";

View File

@@ -84,3 +84,4 @@ extern std::string const infiniteLoopWasmHex;
extern std::string const startLoopHex;
extern std::string const badAllocHex;
extern std::string const badAlignHex;

View File

@@ -196,8 +196,16 @@ locateField(STObject const& obj, Slice const& locator)
if (locator.empty() || (locator.size() & 3)) // must be multiple of 4
return Unexpected(HostFunctionError::LOCATOR_MALFORMED);
int32_t const* locPtr = reinterpret_cast<int32_t const*>(locator.data());
int32_t const locSize = locator.size() / 4;
int32_t locBuf[maxWasmParamLength / sizeof(int32_t)];
int32_t const* locPtr = &locBuf[0];
int32_t const locSize = locator.size() / sizeof(int32_t);
uintptr_t p = reinterpret_cast<uintptr_t>(locator.data());
if (p & (alignof(int32_t) - 1)) // unaligned
memcpy(&locBuf[0], locator.data(), locator.size());
else
locPtr = reinterpret_cast<int32_t const*>(locator.data());
STBase const* field = nullptr;
auto const& knownSFields = SField::getKnownCodeToField();

View File

@@ -71,7 +71,14 @@ getDataUInt64(IW const* runtime, wasm_val_vec_t const* params, int32_t& i)
if (r->size() != sizeof(uint64_t))
return Unexpected(HostFunctionError::INVALID_PARAMS);
return *reinterpret_cast<uint64_t const*>(r->data());
uint64_t x;
uintptr_t p = reinterpret_cast<uintptr_t>(r->data());
if (p & (alignof(uint64_t) - 1)) // unaligned
memcpy(&x, r->data(), sizeof(uint64_t));
else
x = *reinterpret_cast<uint64_t const*>(r->data());
return x;
}
template <class IW>