diff --git a/include/proxy-wasm/exports.h b/include/proxy-wasm/exports.h index ded6419..2451d51 100644 --- a/include/proxy-wasm/exports.h +++ b/include/proxy-wasm/exports.h @@ -44,12 +44,13 @@ template size_t pairsSize(const Pairs &result) { template void marshalPairs(const Pairs &result, char *buffer) { char *b = buffer; - *reinterpret_cast(b) = result.size(); + bool reverse = "null" != contextOrEffectiveContext()->wasmVm()->runtime(); + *reinterpret_cast(b) = reverse ? htowasm(result.size()) : result.size(); b += sizeof(uint32_t); for (auto &p : result) { - *reinterpret_cast(b) = p.first.size(); + *reinterpret_cast(b) = reverse ? htowasm(p.first.size()) : p.first.size(); b += sizeof(uint32_t); - *reinterpret_cast(b) = p.second.size(); + *reinterpret_cast(b) = reverse ? htowasm(p.second.size()) : p.second.size(); b += sizeof(uint32_t); } for (auto &p : result) { diff --git a/include/proxy-wasm/word.h b/include/proxy-wasm/word.h index e96fdfb..559471e 100644 --- a/include/proxy-wasm/word.h +++ b/include/proxy-wasm/word.h @@ -21,6 +21,16 @@ namespace proxy_wasm { #include "proxy_wasm_common.h" +// Use byteswap functions only when compiling for big-endian platforms. +#if defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && \ + __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +#define htowasm(x) __builtin_bswap32(x) +#define wasmtoh(x) __builtin_bswap32(x) +#else +#define htowasm(x) (x) +#define wasmtoh(x) (x) +#endif + // Represents a Wasm-native word-sized datum. On 32-bit VMs, the high bits are always zero. // The Wasm/VM API treats all bits as significant. struct Word { diff --git a/src/exports.cc b/src/exports.cc index 0922b2d..3fe1ab8 100644 --- a/src/exports.cc +++ b/src/exports.cc @@ -46,16 +46,22 @@ Pairs toPairs(std::string_view buffer) { if (buffer.size() < sizeof(uint32_t)) { return {}; } - auto size = *reinterpret_cast(b); + bool reverse = "null" != contextOrEffectiveContext()->wasmVm()->runtime(); + auto size = reverse ? wasmtoh(*reinterpret_cast(b)) + : *reinterpret_cast(b); b += sizeof(uint32_t); if (sizeof(uint32_t) + size * 2 * sizeof(uint32_t) > buffer.size()) { return {}; } result.resize(size); for (uint32_t i = 0; i < size; i++) { - result[i].first = std::string_view(nullptr, *reinterpret_cast(b)); + result[i].first = + std::string_view(nullptr, reverse ? wasmtoh(*reinterpret_cast(b)) + : *reinterpret_cast(b)); b += sizeof(uint32_t); - result[i].second = std::string_view(nullptr, *reinterpret_cast(b)); + result[i].second = + std::string_view(nullptr, reverse ? wasmtoh(*reinterpret_cast(b)) + : *reinterpret_cast(b)); b += sizeof(uint32_t); } for (auto &p : result) { @@ -652,6 +658,7 @@ Word grpc_send(Word token, Word message_ptr, Word message_size, Word end_stream) // logs. Word writevImpl(Word fd, Word iovs, Word iovs_len, Word *nwritten_ptr) { auto context = contextOrEffectiveContext(); + bool reverse = "null" != context->wasmVm()->runtime(); // Read syscall args. uint64_t log_level; @@ -675,7 +682,9 @@ Word writevImpl(Word fd, Word iovs, Word iovs_len, Word *nwritten_ptr) { } const uint32_t *iovec = reinterpret_cast(memslice.value().data()); if (iovec[1] /* buf_len */) { - memslice = context->wasmVm()->getMemory(iovec[0] /* buf */, iovec[1] /* buf_len */); + auto iovec0 = reverse ? wasmtoh(iovec[0]) : iovec[0]; + auto iovec1 = reverse ? wasmtoh(iovec[1]) : iovec[1]; + memslice = context->wasmVm()->getMemory(iovec0 /* buf */, iovec1 /* buf_len */); if (!memslice) { return 21; // __WASI_EFAULT } diff --git a/src/signature_util.cc b/src/signature_util.cc index d4585fe..633539c 100644 --- a/src/signature_util.cc +++ b/src/signature_util.cc @@ -83,6 +83,7 @@ bool SignatureUtil::verifySignature(std::string_view bytecode, std::string &mess uint32_t alg_id; std::memcpy(&alg_id, payload.data(), sizeof(uint32_t)); + alg_id = wasmtoh(alg_id); if (alg_id != 2) { message = "Signature has a wrong alg_id (want: 2, is: " + std::to_string(alg_id) + ")"; @@ -90,7 +91,7 @@ bool SignatureUtil::verifySignature(std::string_view bytecode, std::string &mess } const auto *signature = reinterpret_cast(payload.data()) + sizeof(uint32_t); - const auto sig_len = payload.size() - sizeof(uint32_t); + const auto sig_len = payload.size() - sizeof(uint32_t); SHA512_CTX ctx; SHA512_Init(&ctx); @@ -105,8 +106,10 @@ bool SignatureUtil::verifySignature(std::string_view bytecode, std::string &mess static const auto ed25519_pubkey = hex2pubkey<32>(PROXY_WASM_VERIFY_WITH_ED25519_PUBKEY); bool retval = true; - EVP_MD_CTX* mctx(EVP_MD_CTX_new()); - EVP_PKEY* key(EVP_PKEY_new_raw_public_key(EVP_PKEY_ED25519, NULL, static_cast(ed25519_pubkey.data()), ed25519_pubkey.size())); + EVP_MD_CTX *mctx(EVP_MD_CTX_new()); + EVP_PKEY *key(EVP_PKEY_new_raw_public_key( + EVP_PKEY_ED25519, NULL, static_cast(ed25519_pubkey.data()), + ed25519_pubkey.size())); if (key == nullptr) { message = "Failed to load ed25519 public key"; @@ -116,7 +119,7 @@ bool SignatureUtil::verifySignature(std::string_view bytecode, std::string &mess message = "Failed to initialize ed25519 digest verify"; retval = false; } - if (retval && !EVP_DigestVerify(mctx, signature, sig_len, hash, sizeof(hash))) { + if (retval && !EVP_DigestVerify(mctx, signature, sig_len, hash, sizeof(hash))) { message = "Signature mismatch"; retval = false; } @@ -124,7 +127,8 @@ bool SignatureUtil::verifySignature(std::string_view bytecode, std::string &mess EVP_PKEY_free(key); EVP_MD_CTX_free(mctx); - if (retval) message = "Wasm signature OK (Ed25519)"; + if (retval) + message = "Wasm signature OK (Ed25519)"; return retval; #endif diff --git a/src/v8/v8.cc b/src/v8/v8.cc index dd33f5b..ea658a9 100644 --- a/src/v8/v8.cc +++ b/src/v8/v8.cc @@ -432,7 +432,7 @@ bool V8::getWord(uint64_t pointer, Word *word) { } uint32_t word32; ::memcpy(&word32, memory_->data() + pointer, size); - word->u64_ = word32; + word->u64_ = wasmtoh(word32); return true; } @@ -441,7 +441,7 @@ bool V8::setWord(uint64_t pointer, Word word) { if (pointer + size > memory_->data_size()) { return false; } - uint32_t word32 = word.u32(); + uint32_t word32 = htowasm(word.u32()); ::memcpy(memory_->data() + pointer, &word32, size); return true; } diff --git a/src/wamr/wamr.cc b/src/wamr/wamr.cc index addc703..87c6031 100644 --- a/src/wamr/wamr.cc +++ b/src/wamr/wamr.cc @@ -339,7 +339,7 @@ bool Wamr::getWord(uint64_t pointer, Word *word) { uint32_t word32; ::memcpy(&word32, wasm_memory_data(memory_.get()) + pointer, size); - word->u64_ = word32; + word->u64_ = wasmtoh(word32); return true; } @@ -348,7 +348,7 @@ bool Wamr::setWord(uint64_t pointer, Word word) { if (pointer + size > wasm_memory_data_size(memory_.get())) { return false; } - uint32_t word32 = word.u32(); + uint32_t word32 = htowasm(word.u32()); ::memcpy(wasm_memory_data(memory_.get()) + pointer, &word32, size); return true; } diff --git a/src/wasmtime/wasmtime.cc b/src/wasmtime/wasmtime.cc index 37146ec..85e90d1 100644 --- a/src/wasmtime/wasmtime.cc +++ b/src/wasmtime/wasmtime.cc @@ -354,7 +354,7 @@ bool Wasmtime::getWord(uint64_t pointer, Word *word) { uint32_t word32; ::memcpy(&word32, wasm_memory_data(memory_.get()) + pointer, size); - word->u64_ = word32; + word->u64_ = wasmtoh(word32); return true; } @@ -363,7 +363,7 @@ bool Wasmtime::setWord(uint64_t pointer, Word word) { if (pointer + size > wasm_memory_data_size(memory_.get())) { return false; } - uint32_t word32 = word.u32(); + uint32_t word32 = htowasm(word.u32()); ::memcpy(wasm_memory_data(memory_.get()) + pointer, &word32, size); return true; } diff --git a/src/wavm/wavm.cc b/src/wavm/wavm.cc index 1b0d738..38b0518 100644 --- a/src/wavm/wavm.cc +++ b/src/wavm/wavm.cc @@ -344,12 +344,12 @@ bool Wavm::getWord(uint64_t pointer, Word *data) { auto p = reinterpret_cast(memory_base_ + pointer); uint32_t data32; memcpy(&data32, p, sizeof(uint32_t)); - data->u64_ = data32; + data->u64_ = wasmtoh(data32); return true; } bool Wavm::setWord(uint64_t pointer, Word data) { - uint32_t data32 = data.u32(); + uint32_t data32 = htowasm(data.u32()); return setMemory(pointer, sizeof(uint32_t), &data32); } diff --git a/test/runtime_test.cc b/test/runtime_test.cc index 7bfd392..f6a8722 100644 --- a/test/runtime_test.cc +++ b/test/runtime_test.cc @@ -56,7 +56,7 @@ TEST_P(TestVM, Memory) { ASSERT_TRUE(vm_->getWord(0x2000, &word)); ASSERT_EQ(100, word.u64_); - int32_t data[2] = {-1, 200}; + uint32_t data[2] = {htowasm(static_cast(-1)), htowasm(200)}; ASSERT_TRUE(vm_->setMemory(0x200, sizeof(int32_t) * 2, static_cast(data))); ASSERT_TRUE(vm_->getWord(0x200, &word)); ASSERT_EQ(-1, static_cast(word.u64_));