1
0
Fork 0

Fix undefined behaviour (#7108)

This commit is contained in:
Simon 2018-10-29 19:02:24 +01:00 committed by Jan
parent 5b71dff64f
commit 84de3f6052
2 changed files with 14 additions and 138 deletions

View File

@ -25,31 +25,6 @@
#include "Endian.h"
// aligned / unaligned access
#if defined(__sparc__) || defined(__arm__)
/* unaligned accesses not allowed */
#undef FUERTE_UNALIGNED_ACCESS
#elif defined(__ppc__) || defined(__POWERPC__) || defined(_M_PPC)
/* unaligned accesses are slow */
#undef FUERTE_UNALIGNED_ACCESS
#elif defined(__i386__) || defined(__x86_64__) || \
defined(_M_IX86) || defined(_M_X64)
/* unaligned accesses should work */
#define FUERTE_UNALIGNED_ACCESS 1
#else
/* unknown platform. better not use unaligned accesses */
#undef FUERTE_UNALIGNED_ACCESS
#endif
// enable unaligned little-endian data access
#undef FUERTE_USE_FAST_UNALIGNED_DATA_ACCESS
#ifdef FUERTE_UNALIGNED_ACCESS
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#define FUERTE_USE_FAST_UNALIGNED_DATA_ACCESS
#endif
#endif
namespace arangodb { namespace fuerte { namespace basics {
/*
@ -57,73 +32,20 @@ namespace arangodb { namespace fuerte { namespace basics {
*/
template<typename T>
inline T uintFromPersistentLittleEndian(uint8_t const* ptr) {
inline T uintFromPersistentLittleEndian(uint8_t const* p) {
static_assert(std::is_unsigned<T>::value, "type must be unsigned");
#ifdef FUERTE_USE_FAST_UNALIGNED_DATA_ACCESS
static_assert(basics::isLittleEndian(), "");
return *reinterpret_cast<T const*>(ptr);
#else
T value = 0;
T x = 0;
uint8_t const* end = ptr + sizeof(T);
do {
value += static_cast<T>(*ptr++) << x;
x += 8;
} while (ptr < end);
return value;
#endif
T value;
memcpy(&value, p, sizeof(T));
return basics::littleToHost<T>(value);
}
/*template<typename T>
inline T uintFromPersistentBigEndian(uint8_t const* p) {
//return basics::bigToHost(uintFromPersistentLittleEndian<T>(p));
static_assert(std::is_unsigned<T>::value, "type must be unsigned");
#ifdef FUERTE_USE_FAST_UNALIGNED_DATA_ACCESS
return basics::bigToHost(*reinterpret_cast<T const*>(p));
#else
T value = 0;
T x = sizeof(T) * 8;
uint8_t const* end = ptr + sizeof(T);
do {
x -= 8;
value += static_cast<T>(*ptr++) << x;
} while (ptr < end);
TRI_ASSERT(x == 0);
return value;
#endif
}*/
template<typename T>
inline void uintToPersistentLittleEndian(uint8_t* ptr, T value) {
inline void uintToPersistentLittleEndian(uint8_t* p, T value) {
static_assert(std::is_unsigned<T>::value, "type must be unsigned");
#ifdef FUERTE_USE_FAST_UNALIGNED_DATA_ACCESS
static_assert(basics::isLittleEndian(), "");
*reinterpret_cast<T*>(ptr) = value;
#else
uint8_t* end = ptr + sizeof(T);
do {
*ptr++ = static_cast<uint8_t>(value & 0xffU);
value >>= 8;
} while (ptr < end);
#endif
value = basics::hostToLittle(value);
memcpy(p, &value, sizeof(T));
}
/*template<typename T>
inline void uintToPersistentBigEndian(std::string& p, T value) {
//uintToPersistentLittleEndian<T>(p, basics::hostToBig(value));
static_assert(std::is_unsigned<T>::value, "type must be unsigned");
#ifdef FUERTE_USE_FAST_UNALIGNED_DATA_ACCESS
value = basics::hostToBig(value);
p.append(reinterpret_cast<const char*>(&value), sizeof(T));
#else
size_t len = sizeof(T) * 8;
do {
len -= 8;
p.push_back(static_cast<char>((value >> len) & 0xFF));
} while (len != 0);
#endif
}*/
}}}
#endif

View File

@ -27,13 +27,6 @@
#include "Basics/Endian.h"
#include "RocksDBEngine/RocksDBTypes.h"
#undef TRI_USE_FAST_UNALIGNED_DATA_ACCESS
#ifdef TRI_UNALIGNED_ACCESS
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#define TRI_USE_FAST_UNALIGNED_DATA_ACCESS
#endif
#endif
namespace arangodb {
namespace rocksutils {
@ -65,71 +58,32 @@ inline double intToDouble(uint64_t i) {
template<typename T>
inline T uintFromPersistentLittleEndian(char const* p) {
static_assert(std::is_unsigned<T>::value, "type must be unsigned");
#ifdef TRI_USE_FAST_UNALIGNED_DATA_ACCESS
static_assert(basics::isLittleEndian(), "");
return *reinterpret_cast<T const*>(p);
#else
T value = 0;
T x = 0;
uint8_t const* ptr = reinterpret_cast<uint8_t const*>(p);
uint8_t const* end = ptr + sizeof(T);
do {
value += static_cast<T>(*ptr++) << x;
x += 8;
} while (ptr < end);
return value;
#endif
T value;
memcpy(&value, p, sizeof(T));
return basics::littleToHost<T>(value);
}
template<typename T>
inline T uintFromPersistentBigEndian(char const* p) {
//return basics::bigToHost(uintFromPersistentLittleEndian<T>(p));
static_assert(std::is_unsigned<T>::value, "type must be unsigned");
#ifdef TRI_USE_FAST_UNALIGNED_DATA_ACCESS
return basics::bigToHost(*reinterpret_cast<T const*>(p));
#else
T value = 0;
T x = sizeof(T) * 8;
uint8_t const* ptr = reinterpret_cast<uint8_t const*>(p);
uint8_t const* end = ptr + sizeof(T);
do {
x -= 8;
value += static_cast<T>(*ptr++) << x;
} while (ptr < end);
TRI_ASSERT(x == 0);
return value;
#endif
T value;
memcpy(&value, p, sizeof(T));
return basics::bigToHost<T>(value);
}
template<typename T>
inline void uintToPersistentLittleEndian(std::string& p, T value) {
static_assert(std::is_unsigned<T>::value, "type must be unsigned");
#ifdef TRI_USE_FAST_UNALIGNED_DATA_ACCESS
static_assert(basics::isLittleEndian(), "");
value = basics::hostToLittle(value);
p.append(reinterpret_cast<const char*>(&value), sizeof(T));
#else
size_t len = 0;
do {
p.push_back(static_cast<char>(value & 0xffU));
value >>= 8;
} while (++len < sizeof(T));
#endif
}
template<typename T>
inline void uintToPersistentBigEndian(std::string& p, T value) {
//uintToPersistentLittleEndian<T>(p, basics::hostToBig(value));
static_assert(std::is_unsigned<T>::value, "type must be unsigned");
#ifdef TRI_USE_FAST_UNALIGNED_DATA_ACCESS
value = basics::hostToBig(value);
p.append(reinterpret_cast<const char*>(&value), sizeof(T));
#else
size_t len = sizeof(T) * 8;
do {
len -= 8;
p.push_back(static_cast<char>((value >> len) & 0xFF));
} while (len != 0);
#endif
}
} // namespace rocksutils