Skip to content

Commit 8b2e653

Browse files
authored
fix: avoid potential unaligned loads, found by fuzzer (#456)
Signed-off-by: Michael Warres <[email protected]>
1 parent 26969ea commit 8b2e653

File tree

1 file changed

+27
-12
lines changed

1 file changed

+27
-12
lines changed

src/pairs_util.cc

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
#include "include/proxy-wasm/pairs_util.h"
1717

18+
#include <cstdint>
1819
#include <cstring>
1920
#include <string_view>
2021
#include <vector>
@@ -25,6 +26,23 @@
2526

2627
namespace proxy_wasm {
2728

29+
namespace {
30+
31+
// Read trivially copyable type from char buffer and return value. Does not
32+
// check if char buffer is large enough to contain instance of `T`.
33+
template <typename T> inline T unalignedLoad(const char *buffer) {
34+
// Checking for undefined behaviour wrt std::memcpy.
35+
static_assert(std::is_trivially_copyable_v<T>,
36+
"type must be trivially copyable to use std::memcpy");
37+
T result;
38+
// Use std::memcpy to get around strict type aliasing rules.
39+
std::memcpy(&result, buffer, sizeof(T));
40+
41+
return result;
42+
}
43+
44+
} // namespace
45+
2846
using Sizes = std::vector<std::pair<uint32_t, uint32_t>>;
2947

3048
size_t PairsUtil::pairsSize(const Pairs &pairs) {
@@ -113,10 +131,13 @@ Pairs PairsUtil::toPairs(std::string_view buffer) {
113131
if (pos + sizeof(uint32_t) > end) {
114132
return {};
115133
}
116-
uint32_t num_pairs = wasmtoh(*reinterpret_cast<const uint32_t *>(pos),
117-
contextOrEffectiveContext() != nullptr
118-
? contextOrEffectiveContext()->wasmVm()->usesWasmByteOrder()
119-
: false);
134+
135+
// clang complains that this is unused when the wasmtoh macro drops its
136+
// second argument on non-big-endian platforms.
137+
[[maybe_unused]] const bool uses_wasm_byte_order =
138+
contextOrEffectiveContext() != nullptr &&
139+
contextOrEffectiveContext()->wasmVm()->usesWasmByteOrder();
140+
uint32_t num_pairs = wasmtoh(unalignedLoad<uint32_t>(pos), uses_wasm_byte_order);
120141
pos += sizeof(uint32_t);
121142

122143
// Check if we're not going to exceed the limit.
@@ -135,20 +156,14 @@ Pairs PairsUtil::toPairs(std::string_view buffer) {
135156
if (pos + sizeof(uint32_t) > end) {
136157
return {};
137158
}
138-
s.first = wasmtoh(*reinterpret_cast<const uint32_t *>(pos),
139-
contextOrEffectiveContext() != nullptr
140-
? contextOrEffectiveContext()->wasmVm()->usesWasmByteOrder()
141-
: false);
159+
s.first = wasmtoh(unalignedLoad<uint32_t>(pos), uses_wasm_byte_order);
142160
pos += sizeof(uint32_t);
143161

144162
// Read value length.
145163
if (pos + sizeof(uint32_t) > end) {
146164
return {};
147165
}
148-
s.second = wasmtoh(*reinterpret_cast<const uint32_t *>(pos),
149-
contextOrEffectiveContext() != nullptr
150-
? contextOrEffectiveContext()->wasmVm()->usesWasmByteOrder()
151-
: false);
166+
s.second = wasmtoh(unalignedLoad<uint32_t>(pos), uses_wasm_byte_order);
152167
pos += sizeof(uint32_t);
153168
}
154169

0 commit comments

Comments
 (0)