Skip to content

Commit 537b944

Browse files
authored
Do not reverse bytes for NullVM. (#282)
Fixes #294. Signed-off-by: Konstantin Maksimov <[email protected]>
1 parent 4fcf895 commit 537b944

File tree

15 files changed

+105
-22
lines changed

15 files changed

+105
-22
lines changed

include/proxy-wasm/null_vm.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ struct NullVm : public WasmVm {
6161
#undef _REGISTER_CALLBACK
6262

6363
void terminate() override {}
64+
bool usesWasmByteOrder() override { return false; }
6465

6566
std::string plugin_name_;
6667
std::unique_ptr<NullVmPlugin> plugin_;

include/proxy-wasm/wasm_vm.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,12 @@ class WasmVm {
303303
*/
304304
virtual void terminate() = 0;
305305

306+
/**
307+
* Byte order flag (host or wasm).
308+
* @return 'false' for a null VM and 'true' for a wasm VM.
309+
*/
310+
virtual bool usesWasmByteOrder() = 0;
311+
306312
bool isFailed() { return failed_ != FailState::Ok; }
307313
void fail(FailState fail_state, std::string_view message) {
308314
integration()->error(message);

include/proxy-wasm/word.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,11 @@ namespace proxy_wasm {
2424
// Use byteswap functions only when compiling for big-endian platforms.
2525
#if defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && \
2626
__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
27-
#define htowasm(x) __builtin_bswap32(x)
28-
#define wasmtoh(x) __builtin_bswap32(x)
27+
#define htowasm(x, vm_uses_wasm_byte_order) ((vm_uses_wasm_byte_order) ? __builtin_bswap32(x) : (x))
28+
#define wasmtoh(x, vm_uses_wasm_byte_order) ((vm_uses_wasm_byte_order) ? __builtin_bswap32(x) : (x))
2929
#else
30-
#define htowasm(x) (x)
31-
#define wasmtoh(x) (x)
30+
#define htowasm(x, vm_uses_wasm_byte_order) (x)
31+
#define wasmtoh(x, vm_uses_wasm_byte_order) (x)
3232
#endif
3333

3434
// Represents a Wasm-native word-sized datum. On 32-bit VMs, the high bits are always zero.

src/exports.cc

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -693,8 +693,9 @@ Word writevImpl(Word fd, Word iovs, Word iovs_len, Word *nwritten_ptr) {
693693
}
694694
const auto *iovec = reinterpret_cast<const uint32_t *>(memslice.value().data());
695695
if (iovec[1] != 0U /* buf_len */) {
696-
memslice = context->wasmVm()->getMemory(wasmtoh(iovec[0]) /* buf */,
697-
wasmtoh(iovec[1]) /* buf_len */);
696+
const auto buf = wasmtoh(iovec[0], context->wasmVm()->usesWasmByteOrder());
697+
const auto buf_len = wasmtoh(iovec[1], context->wasmVm()->usesWasmByteOrder());
698+
memslice = context->wasmVm()->getMemory(buf, buf_len);
698699
if (!memslice) {
699700
return 21; // __WASI_EFAULT
700701
}

src/pairs_util.cc

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <string_view>
2020
#include <vector>
2121

22+
#include "include/proxy-wasm/exports.h"
2223
#include "include/proxy-wasm/limits.h"
2324
#include "include/proxy-wasm/word.h"
2425

@@ -45,7 +46,10 @@ bool PairsUtil::marshalPairs(const Pairs &pairs, char *buffer, size_t size) {
4546
const char *end = buffer + size;
4647

4748
// Write number of pairs.
48-
uint32_t num_pairs = htowasm(pairs.size());
49+
uint32_t num_pairs =
50+
htowasm(pairs.size(), contextOrEffectiveContext() != nullptr
51+
? contextOrEffectiveContext()->wasmVm()->usesWasmByteOrder()
52+
: false);
4953
if (pos + sizeof(uint32_t) > end) {
5054
return false;
5155
}
@@ -54,15 +58,21 @@ bool PairsUtil::marshalPairs(const Pairs &pairs, char *buffer, size_t size) {
5458

5559
for (const auto &p : pairs) {
5660
// Write name length.
57-
uint32_t name_len = htowasm(p.first.size());
61+
uint32_t name_len =
62+
htowasm(p.first.size(), contextOrEffectiveContext() != nullptr
63+
? contextOrEffectiveContext()->wasmVm()->usesWasmByteOrder()
64+
: false);
5865
if (pos + sizeof(uint32_t) > end) {
5966
return false;
6067
}
6168
::memcpy(pos, &name_len, sizeof(uint32_t));
6269
pos += sizeof(uint32_t);
6370

6471
// Write value length.
65-
uint32_t value_len = htowasm(p.second.size());
72+
uint32_t value_len =
73+
htowasm(p.second.size(), contextOrEffectiveContext() != nullptr
74+
? contextOrEffectiveContext()->wasmVm()->usesWasmByteOrder()
75+
: false);
6676
if (pos + sizeof(uint32_t) > end) {
6777
return false;
6878
}
@@ -103,7 +113,10 @@ Pairs PairsUtil::toPairs(std::string_view buffer) {
103113
if (pos + sizeof(uint32_t) > end) {
104114
return {};
105115
}
106-
uint32_t num_pairs = wasmtoh(*reinterpret_cast<const uint32_t *>(pos));
116+
uint32_t num_pairs = wasmtoh(*reinterpret_cast<const uint32_t *>(pos),
117+
contextOrEffectiveContext() != nullptr
118+
? contextOrEffectiveContext()->wasmVm()->usesWasmByteOrder()
119+
: false);
107120
pos += sizeof(uint32_t);
108121

109122
// Check if we're not going to exceed the limit.
@@ -122,14 +135,20 @@ Pairs PairsUtil::toPairs(std::string_view buffer) {
122135
if (pos + sizeof(uint32_t) > end) {
123136
return {};
124137
}
125-
s.first = wasmtoh(*reinterpret_cast<const uint32_t *>(pos));
138+
s.first = wasmtoh(*reinterpret_cast<const uint32_t *>(pos),
139+
contextOrEffectiveContext() != nullptr
140+
? contextOrEffectiveContext()->wasmVm()->usesWasmByteOrder()
141+
: false);
126142
pos += sizeof(uint32_t);
127143

128144
// Read value length.
129145
if (pos + sizeof(uint32_t) > end) {
130146
return {};
131147
}
132-
s.second = wasmtoh(*reinterpret_cast<const uint32_t *>(pos));
148+
s.second = wasmtoh(*reinterpret_cast<const uint32_t *>(pos),
149+
contextOrEffectiveContext() != nullptr
150+
? contextOrEffectiveContext()->wasmVm()->usesWasmByteOrder()
151+
: false);
133152
pos += sizeof(uint32_t);
134153
}
135154

src/signature_util.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ bool SignatureUtil::verifySignature(std::string_view bytecode, std::string &mess
8686

8787
uint32_t alg_id;
8888
std::memcpy(&alg_id, payload.data(), sizeof(uint32_t));
89-
alg_id = wasmtoh(alg_id);
89+
alg_id = wasmtoh(alg_id, true);
9090

9191
if (alg_id != 2) {
9292
message = "Signature has a wrong alg_id (want: 2, is: " + std::to_string(alg_id) + ")";

src/v8/v8.cc

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ class V8 : public WasmVm {
105105
#undef _GET_MODULE_FUNCTION
106106

107107
void terminate() override;
108+
bool usesWasmByteOrder() override { return true; }
108109

109110
private:
110111
wasm::own<wasm::Trap> trap(std::string message);
@@ -503,7 +504,7 @@ bool V8::getWord(uint64_t pointer, Word *word) {
503504
}
504505
uint32_t word32;
505506
::memcpy(&word32, memory_->data() + pointer, size);
506-
word->u64_ = wasmtoh(word32);
507+
word->u64_ = wasmtoh(word32, true);
507508
return true;
508509
}
509510

@@ -516,7 +517,7 @@ bool V8::setWord(uint64_t pointer, Word word) {
516517
if (pointer + size > memory_->data_size()) {
517518
return false;
518519
}
519-
uint32_t word32 = htowasm(word.u32());
520+
uint32_t word32 = htowasm(word.u32(), true);
520521
::memcpy(memory_->data() + pointer, &word32, size);
521522
return true;
522523
}

src/wamr/wamr.cc

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ class Wamr : public WasmVm {
8787
#undef _GET_MODULE_FUNCTION
8888

8989
void terminate() override {}
90+
bool usesWasmByteOrder() override { return true; }
9091

9192
private:
9293
template <typename... Args>
@@ -368,7 +369,7 @@ bool Wamr::getWord(uint64_t pointer, Word *word) {
368369

369370
uint32_t word32;
370371
::memcpy(&word32, wasm_memory_data(memory_.get()) + pointer, size);
371-
word->u64_ = wasmtoh(word32);
372+
word->u64_ = wasmtoh(word32, true);
372373
return true;
373374
}
374375

@@ -377,7 +378,7 @@ bool Wamr::setWord(uint64_t pointer, Word word) {
377378
if (pointer + size > wasm_memory_data_size(memory_.get())) {
378379
return false;
379380
}
380-
uint32_t word32 = htowasm(word.u32());
381+
uint32_t word32 = htowasm(word.u32(), true);
381382
::memcpy(wasm_memory_data(memory_.get()) + pointer, &word32, size);
382383
return true;
383384
}

src/wasmedge/wasmedge.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,7 @@ class WasmEdge : public WasmVm {
281281
std::function<R(ContextBase *, Args...)> *function);
282282

283283
void terminate() override {}
284+
bool usesWasmByteOrder() override { return true; }
284285

285286
WasmEdgeLoaderPtr loader_;
286287
WasmEdgeValidatorPtr validator_;

src/wasmtime/wasmtime.cc

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ class Wasmtime : public WasmVm {
9898
std::function<R(ContextBase *, Args...)> *function);
9999

100100
void terminate() override {}
101+
bool usesWasmByteOrder() override { return true; }
101102

102103
WasmStorePtr store_;
103104
WasmModulePtr module_;
@@ -394,7 +395,7 @@ bool Wasmtime::getWord(uint64_t pointer, Word *word) {
394395

395396
uint32_t word32;
396397
::memcpy(&word32, wasm_memory_data(memory_.get()) + pointer, size);
397-
word->u64_ = wasmtoh(word32);
398+
word->u64_ = wasmtoh(word32, true);
398399
return true;
399400
}
400401

@@ -403,7 +404,7 @@ bool Wasmtime::setWord(uint64_t pointer, Word word) {
403404
if (pointer + size > wasm_memory_data_size(memory_.get())) {
404405
return false;
405406
}
406-
uint32_t word32 = htowasm(word.u32());
407+
uint32_t word32 = htowasm(word.u32(), true);
407408
::memcpy(wasm_memory_data(memory_.get()) + pointer, &word32, size);
408409
return true;
409410
}

src/wavm/wavm.cc

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,7 @@ struct Wavm : public WasmVm {
230230
#undef _REGISTER_CALLBACK
231231

232232
void terminate() override {}
233+
bool usesWasmByteOrder() override { return true; }
233234

234235
IR::Module ir_module_;
235236
WAVM::Runtime::ModuleRef module_ = nullptr;
@@ -389,12 +390,12 @@ bool Wavm::getWord(uint64_t pointer, Word *data) {
389390
auto *p = reinterpret_cast<char *>(memory_base_ + pointer);
390391
uint32_t data32;
391392
memcpy(&data32, p, sizeof(uint32_t));
392-
data->u64_ = wasmtoh(data32);
393+
data->u64_ = wasmtoh(data32, true);
393394
return true;
394395
}
395396

396397
bool Wavm::setWord(uint64_t pointer, Word data) {
397-
uint32_t data32 = htowasm(data.u32());
398+
uint32_t data32 = htowasm(data.u32(), true);
398399
return setMemory(pointer, sizeof(uint32_t), &data32);
399400
}
400401

test/BUILD

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,17 @@ cc_test(
165165
],
166166
)
167167

168+
cc_test(
169+
name = "pairs_util_test",
170+
srcs = ["pairs_util_test.cc"],
171+
linkstatic = 1,
172+
deps = [
173+
"//:lib",
174+
"@com_google_googletest//:gtest",
175+
"@com_google_googletest//:gtest_main",
176+
],
177+
)
178+
168179
cc_library(
169180
name = "utility_lib",
170181
testonly = True,

test/null_vm_test.cc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,4 +73,10 @@ TEST_F(BaseVmTest, NullVmStartup) {
7373
EXPECT_NE(test_null_vm_plugin, nullptr);
7474
}
7575

76+
TEST_F(BaseVmTest, ByteOrder) {
77+
auto wasm_vm = createNullVm();
78+
EXPECT_TRUE(wasm_vm->load("test_null_vm_plugin", {}, {}));
79+
EXPECT_FALSE(wasm_vm->usesWasmByteOrder());
80+
}
81+
7682
} // namespace proxy_wasm

test/pairs_util_test.cc

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Copyright 2022 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include "include/proxy-wasm/pairs_util.h"
16+
#include "gtest/gtest.h"
17+
18+
namespace proxy_wasm {
19+
20+
TEST(PairsUtilTest, EncodeDecode) {
21+
proxy_wasm::Pairs pairs1;
22+
std::string data1("some_data");
23+
auto size_str = std::to_string(data1.size());
24+
pairs1.push_back({data1, size_str});
25+
std::vector<char> buffer(PairsUtil::pairsSize(pairs1));
26+
EXPECT_TRUE(PairsUtil::marshalPairs(pairs1, buffer.data(), buffer.size()));
27+
auto pairs2 = PairsUtil::toPairs(std::string_view(buffer.data(), buffer.size()));
28+
EXPECT_EQ(pairs2.size(), pairs1.size());
29+
EXPECT_EQ(pairs2[0].first, pairs1[0].first);
30+
EXPECT_EQ(pairs2[0].second, pairs1[0].second);
31+
}
32+
33+
} // namespace proxy_wasm

test/wasm_vm_test.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ TEST_P(TestVm, Memory) {
5353
ASSERT_TRUE(vm_->getWord(0x2000, &word));
5454
ASSERT_EQ(100, word.u64_);
5555

56-
uint32_t data[2] = {htowasm(static_cast<uint32_t>(-1)), htowasm(200)};
56+
uint32_t data[2] = {htowasm(static_cast<uint32_t>(-1), vm_->usesWasmByteOrder()),
57+
htowasm(200, vm_->usesWasmByteOrder())};
5758
ASSERT_TRUE(vm_->setMemory(0x200, sizeof(int32_t) * 2, static_cast<void *>(data)));
5859
ASSERT_TRUE(vm_->getWord(0x200, &word));
5960
ASSERT_EQ(-1, static_cast<int32_t>(word.u64_));

0 commit comments

Comments
 (0)