Fixed potential strict-aliasing violation in big-endian code.

Also added a test.

Tested on: Linux.

Change-Id: I7b3230f8f6043eec139d5e3e8c9cb45814124274
parent 7e803c41
......@@ -186,14 +186,20 @@ template<typename T> T EndianSwap(T t) {
if (sizeof(T) == 1) { // Compile-time if-then's.
return t;
} else if (sizeof(T) == 2) {
auto r = FLATBUFFERS_BYTESWAP16(*reinterpret_cast<uint16_t *>(&t));
return *reinterpret_cast<T *>(&r);
union { T t; uint16_t i; } u;
u.t = t;
u.i = FLATBUFFERS_BYTESWAP16(u.i);
return u.t;
} else if (sizeof(T) == 4) {
auto r = FLATBUFFERS_BYTESWAP32(*reinterpret_cast<uint32_t *>(&t));
return *reinterpret_cast<T *>(&r);
union { T t; uint32_t i; } u;
u.t = t;
u.i = FLATBUFFERS_BYTESWAP32(u.i);
return u.t;
} else if (sizeof(T) == 8) {
auto r = FLATBUFFERS_BYTESWAP64(*reinterpret_cast<uint64_t *>(&t));
return *reinterpret_cast<T *>(&r);
union { T t; uint64_t i; } u;
u.t = t;
u.i = FLATBUFFERS_BYTESWAP64(u.i);
return u.t;
} else {
assert(0);
}
......
......@@ -1803,6 +1803,16 @@ void TypeAliasesTest()
TEST_EQ(sizeof(ta->f64()), 8);
}
void EndianSwapTest() {
TEST_EQ(flatbuffers::EndianSwap(static_cast<int16_t>(0x1234)),
0x3412);
TEST_EQ(flatbuffers::EndianSwap(static_cast<int32_t>(0x12345678)),
0x78563412);
TEST_EQ(flatbuffers::EndianSwap(static_cast<int64_t>(0x1234567890ABCDEF)),
0xEFCDAB9078563412);
TEST_EQ(flatbuffers::EndianSwap(flatbuffers::EndianSwap(3.14f)), 3.14f);
}
int main(int /*argc*/, const char * /*argv*/[]) {
#if defined(FLATBUFFERS_MEMORY_LEAK_TRACKING) && \
defined(_MSC_VER) && defined(_DEBUG)
......@@ -1866,6 +1876,7 @@ int main(int /*argc*/, const char * /*argv*/[]) {
ConformTest();
ParseProtoBufAsciiTest();
TypeAliasesTest();
EndianSwapTest();
FlexBuffersTest();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment