| From 4fd16633a8c379971425f7fd482152f163b09158 Mon Sep 17 00:00:00 2001 |
| From: Paul Burton <Paul.Burton@imgtec.com> |
| Date: Fri, 17 Sep 2010 14:08:57 +0100 |
| Subject: [PATCH] Endianness macros should not dereference unaligned pointers |
| |
| The LE_*/BE_* macros previously worked by casting the pointer passed to them to a pointer to the correct integer type, then dereferencing it. This will not work on architectures which don't allow unaligned data access. Instead, access one byte at a time and shift to form the value. |
| --- |
| src/bswap.h | 59 +++++++++++++++++++++++++++++++++++++++++++---------------- |
| 1 files changed, 43 insertions(+), 16 deletions(-) |
| |
| diff --git a/src/bswap.h b/src/bswap.h |
| index b731da7..59e8716 100644 |
| --- a/src/bswap.h |
| +++ b/src/bswap.h |
| @@ -21,23 +21,50 @@ |
| */ |
| |
| |
| -/* Go cheap now, will rip out glib later. *Sigh* */ |
| -#include <glib.h> |
| - |
| -/* NOTE: |
| - * Now, to clear up confusion: LE_XX means "from LE to native, XX bits wide" |
| - * I know it's not very clear naming (tell me about it, I |
| - * misinterpreted in first version and caused bad nasty bug, *sigh*), |
| - * but that's inherited code, will clean up as things go |
| - * Oh, and one more thing -- they take *pointers*, not actual ints |
| - */ |
| +#include <stdint.h> |
| + |
| +#define SWAP_ENDIAN_16(val) \ |
| + (val[1] | (val[0] << 8)) |
| +#define SWAP_ENDIAN_32(val) \ |
| + (val[3] | (val[2] << 8) | (val[1] << 16) | (val[0] << 24)) |
| +#define SWAP_ENDIAN_64(val) \ |
| + (val[7] | (val[6] << 8) | (val[5] << 16) | (val[4] << 24) | \ |
| + ((uint64_t)val[3] << 32) | ((uint64_t)val[2] << 40) | \ |
| + ((uint64_t)val[1] << 48) | ((uint64_t)val[0] << 56)) |
| + |
| +#define SAME_ENDIAN_16(val) \ |
| + (val[0] | (val[1] << 8)) |
| +#define SAME_ENDIAN_32(val) \ |
| + (val[0] | (val[1] << 8) | (val[2] << 16) | (val[3] << 24)) |
| +#define SAME_ENDIAN_64(val) \ |
| + (val[0] | (val[1] << 8) | (val[2] << 16) | (val[3] << 24) | \ |
| + ((uint64_t)val[4] << 32) | ((uint64_t)val[5] << 40) | \ |
| + ((uint64_t)val[6] << 48) | ((uint64_t)val[7] << 56)) |
| + |
| +#ifndef WORDS_BIGENDIAN |
| + |
| +/* Little endian */ |
| + |
| +#define LE_16(val) SAME_ENDIAN_16(((uint8_t *)(val))) |
| +#define LE_32(val) SAME_ENDIAN_32(((uint8_t *)(val))) |
| +#define LE_64(val) SAME_ENDIAN_64(((uint8_t *)(val))) |
| +#define BE_16(val) SWAP_ENDIAN_16(((uint8_t *)(val))) |
| +#define BE_32(val) SWAP_ENDIAN_32(((uint8_t *)(val))) |
| +#define BE_64(val) SWAP_ENDIAN_64(((uint8_t *)(val))) |
| + |
| +#elif WORDS_BIGENDIAN == 1 |
| + |
| +/* Big endian */ |
| |
| -#define LE_16(val) (GINT16_FROM_LE (*((u_int16_t*)(val)))) |
| -#define BE_16(val) (GINT16_FROM_BE (*((u_int16_t*)(val)))) |
| -#define LE_32(val) (GINT32_FROM_LE (*((u_int32_t*)(val)))) |
| -#define BE_32(val) (GINT32_FROM_BE (*((u_int32_t*)(val)))) |
| +#define LE_16(val) SWAP_ENDIAN_16(((uint8_t *)(val))) |
| +#define LE_32(val) SWAP_ENDIAN_32(((uint8_t *)(val))) |
| +#define LE_64(val) SWAP_ENDIAN_64(((uint8_t *)(val))) |
| +#define BE_16(val) SAME_ENDIAN_16(((uint8_t *)(val))) |
| +#define BE_32(val) SAME_ENDIAN_32(((uint8_t *)(val))) |
| +#define BE_64(val) SAME_ENDIAN_64(((uint8_t *)(val))) |
| |
| -#define LE_64(val) (GINT64_FROM_LE (*((u_int64_t*)(val)))) |
| -#define BE_64(val) (GINT64_FROM_BE (*((u_int64_t*)(val)))) |
| +#else |
| +#error Unknown endianness! |
| +#endif |
| |
| #endif /* BSWAP_H_INCLUDED */ |
| -- |
| 1.7.2.2 |
| |