From 0e3cec02987e801db4e51b8c21d74256d2be7c75 Mon Sep 17 00:00:00 2001 From: vinayakray19 Date: Thu, 18 Jun 2026 18:01:10 +0530 Subject: [PATCH 1/2] Fix setDatatype endianness when writing to Wasm memory. Wasm linear memory is little-endian, but setDatatype wrote host-native integer bytes via setMemory. On big-endian hosts such as s390x this broke hostcalls that return primitives (for example proxy_get_log_level) and could cause plugin configure failures. Apply htowasm using the VM's usesWasmByteOrder flag, matching setWord. Add a regression test that asserts setDatatype stores little-endian bytes. Signed-off-by: vinayakray19 --- include/proxy-wasm/wasm.h | 3 ++- test/wasm_vm_test.cc | 25 +++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/include/proxy-wasm/wasm.h b/include/proxy-wasm/wasm.h index 3794c6a89..10c16a794 100644 --- a/include/proxy-wasm/wasm.h +++ b/include/proxy-wasm/wasm.h @@ -448,7 +448,8 @@ inline bool WasmBase::copyToPointerSize(std::string_view s, uint64_t ptr_ptr, ui } template inline bool WasmBase::setDatatype(uint64_t ptr, const T &t) { - return wasm_vm_->setMemory(ptr, sizeof(T), &t); + T value = htowasm(t, wasm_vm_->usesWasmByteOrder()); + return wasm_vm_->setMemory(ptr, sizeof(T), &value); } } // namespace proxy_wasm diff --git a/test/wasm_vm_test.cc b/test/wasm_vm_test.cc index d792c63df..5795235d4 100644 --- a/test/wasm_vm_test.cc +++ b/test/wasm_vm_test.cc @@ -93,6 +93,31 @@ TEST_P(TestVm, Memory) { ASSERT_EQ(200, static_cast(word.u64_)); } +TEST_P(TestVm, SetDatatypeWritesLittleEndian) { + if (engine_ == "null") { + // NullVm stores host-endian values in memory. + return; + } + auto source = readTestWasmFile("abi_export.wasm"); + ASSERT_FALSE(source.empty()); + auto local_vm = makeVm(engine_); + TestWasm wasm(std::move(local_vm)); + ASSERT_TRUE(wasm.load(source, false)); + ASSERT_TRUE(wasm.initialize()); + + const uint64_t ptr = 0x1000; + const uint32_t value = 0x02000001U; + + ASSERT_TRUE(wasm.setDatatype(ptr, value)); + + auto mem = wasm.wasm_vm()->getMemory(ptr, sizeof(uint32_t)); + ASSERT_TRUE(mem.has_value()); + EXPECT_EQ(static_cast(mem->data()[0]), 0x01U); + EXPECT_EQ(static_cast(mem->data()[1]), 0x00U); + EXPECT_EQ(static_cast(mem->data()[2]), 0x00U); + EXPECT_EQ(static_cast(mem->data()[3]), 0x02U); +} + TEST_P(TestVm, Clone) { if (vm_->cloneable() == proxy_wasm::Cloneable::NotCloneable) { return; From 810cace71568ad260f5f7a46ac1423af2ae70783 Mon Sep 17 00:00:00 2001 From: vinayakray19 Date: Thu, 18 Jun 2026 21:53:06 +0530 Subject: [PATCH 2/2] Add end-to-end endianness test for setDatatype via get_log_level. Extend endianness.wasm with test_host_set_datatype, which calls proxy_get_log_level and verifies the u32 written by the host via setDatatype. EndiannessContext returns 0x02000001 so the test fails on big-endian hosts if bytes are not converted to Wasm little-endian order. Signed-off-by: vinayakray19 --- test/endianness_test.cc | 11 +++++++++++ test/test_data/endianness.rs | 22 +++++++++++++++++++++- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/test/endianness_test.cc b/test/endianness_test.cc index d8a97ddde..a34d44b56 100644 --- a/test/endianness_test.cc +++ b/test/endianness_test.cc @@ -33,6 +33,10 @@ class EndiannessContext : public TestContext { // opposed to output parameter. return static_cast(3333333333U); } + uint32_t getLogLevel() override { + // Asymmetric byte pattern to catch host-endian writes via setDatatype. + return 0x02000001U; + } }; class EndiannessWasm : public TestWasm { @@ -149,6 +153,13 @@ TEST_P(EndiannessTest, WasmCallReadsBufferPassedByHost) { ASSERT_TRUE(test_buffer_from_host(context_)) << context_->getLog(); } +TEST_P(EndiannessTest, HostCallSetDatatype) { + WasmCallWord<0> test_host_set_datatype; + wasm_->wasm_vm()->getFunction("test_host_set_datatype", &test_host_set_datatype); + + EXPECT_TRUE(test_host_set_datatype(context_)) << context_->getLog(); +} + GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EndiannessTest); } // namespace diff --git a/test/test_data/endianness.rs b/test/test_data/endianness.rs index a2a909bbe..1e065a7b6 100644 --- a/test/test_data/endianness.rs +++ b/test/test_data/endianness.rs @@ -33,7 +33,7 @@ pub extern "C" fn _initialize() { } #[no_mangle] -pub extern "C" fn proxy_abi_version_0_2_0() {} +pub extern "C" fn proxy_abi_version_0_2_1() {} #[no_mangle] pub extern "C" fn proxy_on_memory_allocate(size: usize) -> *mut u8 { @@ -177,3 +177,23 @@ pub extern "C" fn test_buffer_from_host() -> bool { } } } + +extern "C" { + // proxy_get_log_level writes the host log level to Wasm memory via setDatatype. + fn proxy_get_log_level(return_level: *mut u32) -> u32; +} + +#[no_mangle] +pub extern "C" fn test_host_set_datatype() -> u32 { + let mut level: u32 = 0; + unsafe { + let status = proxy_get_log_level(&mut level); + if status != 0 { + panic!("unexpected status: {}", status); + } + if level != 0x02000001 { + panic!("unexpected level: {}", level); + } + } + return 1; +}