mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-01-29 15:43:52 +00:00
Add build def ZT_NO_TYPE_PUNNING, which when defined disables type punning code that might cause unaligned access errors on architectures that care (e.g. Android/ARM)
This commit is contained in:
parent
412389ec75
commit
a297e4a5bf
@ -39,7 +39,7 @@
|
||||
#include "Constants.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
#ifdef __GNUC__
|
||||
#if defined(__GNUC__) && (!defined(ZT_NO_TYPE_PUNNING))
|
||||
#define ZT_VAR_MAY_ALIAS __attribute__((__may_alias__))
|
||||
#else
|
||||
#define ZT_VAR_MAY_ALIAS
|
||||
@ -204,15 +204,19 @@ public:
|
||||
{
|
||||
if ((i + sizeof(T)) > _l)
|
||||
throw std::out_of_range("Buffer: setAt() beyond end of data");
|
||||
#ifdef ZT_NO_TYPE_PUNNING
|
||||
uint8_t *p = reinterpret_cast<uint8_t *>(_b + i);
|
||||
for(unsigned int x=1;x<=sizeof(T);++x)
|
||||
*(p++) = (uint8_t)(v >> (8 * (sizeof(T) - x)));
|
||||
#else
|
||||
T *const ZT_VAR_MAY_ALIAS p = reinterpret_cast<T *>(_b + i);
|
||||
*p = Utils::hton(v);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a primitive integer value at a given position
|
||||
*
|
||||
* This behaves like set() in reverse.
|
||||
*
|
||||
* @param i Index to get integer
|
||||
* @tparam T Integer type (e.g. uint16_t, int64_t)
|
||||
* @return Integer value
|
||||
@ -223,8 +227,18 @@ public:
|
||||
{
|
||||
if ((i + sizeof(T)) > _l)
|
||||
throw std::out_of_range("Buffer: at() beyond end of data");
|
||||
#ifdef ZT_NO_TYPE_PUNNING
|
||||
T v = 0;
|
||||
const uint8_t *p = reinterpret_cast<const uint8_t *>(_b + i);
|
||||
for(unsigned int x=0;x<sizeof(T);++x) {
|
||||
v <<= 8;
|
||||
v |= (T)*(p++);
|
||||
}
|
||||
return v;
|
||||
#else
|
||||
const T *const ZT_VAR_MAY_ALIAS p = reinterpret_cast<const T *>(_b + i);
|
||||
return Utils::ntoh(*p);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
@ -240,8 +254,14 @@ public:
|
||||
{
|
||||
if ((_l + sizeof(T)) > C)
|
||||
throw std::out_of_range("Buffer: append beyond capacity");
|
||||
#ifdef ZT_NO_TYPE_PUNNING
|
||||
uint8_t *p = reinterpret_cast<uint8_t *>(_b + _l);
|
||||
for(unsigned int x=1;x<=sizeof(T);++x)
|
||||
*(p++) = (uint8_t)(v >> (8 * (sizeof(T) - x)));
|
||||
#else
|
||||
T *const ZT_VAR_MAY_ALIAS p = reinterpret_cast<T *>(_b + _l);
|
||||
*p = Utils::hton(v);
|
||||
#endif
|
||||
_l += sizeof(T);
|
||||
}
|
||||
|
||||
|
@ -19,13 +19,15 @@
|
||||
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
|
||||
// Slow version that does not use type punning
|
||||
//#define U8TO32_LITTLE(p) ( ((uint32_t)(p)[0]) | ((uint32_t)(p)[1] << 8) | ((uint32_t)(p)[2] << 16) | ((uint32_t)(p)[3] << 24) )
|
||||
//static inline void U32TO8_LITTLE(uint8_t *const c,const uint32_t v) { c[0] = (uint8_t)v; c[1] = (uint8_t)(v >> 8); c[2] = (uint8_t)(v >> 16); c[3] = (uint8_t)(v >> 24); }
|
||||
|
||||
#ifdef ZT_NO_TYPE_PUNNING
|
||||
// Slower version that does not use type punning
|
||||
#define U8TO32_LITTLE(p) ( ((uint32_t)(p)[0]) | ((uint32_t)(p)[1] << 8) | ((uint32_t)(p)[2] << 16) | ((uint32_t)(p)[3] << 24) )
|
||||
static inline void U32TO8_LITTLE(uint8_t *const c,const uint32_t v) { c[0] = (uint8_t)v; c[1] = (uint8_t)(v >> 8); c[2] = (uint8_t)(v >> 16); c[3] = (uint8_t)(v >> 24); }
|
||||
#else
|
||||
// Fast version that just does 32-bit load/store
|
||||
#define U8TO32_LITTLE(p) (*((const uint32_t *)((const void *)(p))))
|
||||
#define U32TO8_LITTLE(c,v) *((uint32_t *)((void *)(c))) = (v)
|
||||
#endif // ZT_NO_TYPE_PUNNING
|
||||
|
||||
#else // __BYTE_ORDER == __BIG_ENDIAN (we don't support anything else... does MIDDLE_ENDIAN even still exist?)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user