From c528844e8128fe8eb7da3269a0b5f5142a5690ff Mon Sep 17 00:00:00 2001 From: Olivier Guiter Date: Wed, 9 Jan 2013 13:42:37 +0100 Subject: [PATCH] types: Fix build error due to unaligned memory access This fix number of build error on architectures that can't handle unaligned memory access (eg. ARM). Most of the code was originally written in BlueZ's bluetooth.h. --- include/types.h | 143 ++++++++++++++++++++++++++++++++++++++++++++++++++++ plugins/nfctype4.c | 4 +- plugins/snep-core.c | 4 +- src/bluetooth.c | 11 +--- src/ndef.c | 13 +++-- src/tlv.c | 2 +- 6 files changed, 155 insertions(+), 22 deletions(-) diff --git a/include/types.h b/include/types.h index bd5b53d..894b7db 100644 --- a/include/types.h +++ b/include/types.h @@ -22,6 +22,8 @@ #ifndef __NEAR_TYPES_H #define __NEAR_TYPES_H +#include + #ifndef FALSE #define FALSE (0) #endif @@ -32,4 +34,145 @@ typedef int near_bool_t; +#define near_get_unaligned(ptr) \ +({ \ + struct __attribute__((packed)) { \ + typeof(*(ptr)) __v; \ + } *__p = (typeof(__p)) (ptr); \ + __p->__v; \ +}) + +#define near_put_unaligned(val, ptr) \ +do { \ + struct __attribute__((packed)) { \ + typeof(*(ptr)) __v; \ + } *__p = (typeof(__p)) (ptr); \ + __p->__v = (val); \ +} while (0) + +#if __BYTE_ORDER == __LITTLE_ENDIAN +static inline uint64_t near_get_le64(const void *ptr) +{ + return near_get_unaligned((const uint64_t *) ptr); +} + +static inline uint64_t near_get_be64(const void *ptr) +{ + return bswap_64(near_get_unaligned((const uint64_t *) ptr)); +} + +static inline uint32_t near_get_le32(const void *ptr) +{ + return near_get_unaligned((const uint32_t *) ptr); +} + +static inline uint32_t near_get_be32(const void *ptr) +{ + return bswap_32(near_get_unaligned((const uint32_t *) ptr)); +} + +static inline uint16_t near_get_le16(const void *ptr) +{ + return near_get_unaligned((const uint16_t *) ptr); +} + +static inline uint16_t near_get_be16(const void *ptr) +{ + return bswap_16(near_get_unaligned((const uint16_t *) ptr)); +} + +static inline void near_put_le64(uint64_t val, const void *ptr) +{ + near_put_unaligned(val, (uint64_t *) ptr); +} + +static inline void near_put_be64(uint64_t val, const void *ptr) +{ + near_put_unaligned(bswap_64(val), (uint64_t *) ptr); +} + +static inline void near_put_le32(uint32_t val, const void *ptr) +{ + near_put_unaligned(val, (uint32_t *) ptr); +} + +static inline void near_put_be32(uint32_t val, const void *ptr) +{ + near_put_unaligned(bswap_32(val), (uint32_t *) ptr); +} + +static inline void near_put_le16(uint16_t val, const void *ptr) +{ + near_put_unaligned(val, (uint16_t *) ptr); +} + +static inline void near_put_be16(uint16_t val, const void *ptr) +{ + near_put_unaligned(bswap_16(val), (uint16_t *) ptr); +} + +#elif __BYTE_ORDER == __BIG_ENDIAN +static inline uint64_t near_get_le64(const void *ptr) +{ + return bswap_64(near_get_unaligned((const uint64_t *) ptr)); +} + +static inline uint64_t near_get_be64(const void *ptr) +{ + return near_get_unaligned((const uint64_t *) ptr); +} + +static inline uint32_t near_get_le32(const void *ptr) +{ + return bswap_32(near_get_unaligned((const uint32_t *) ptr)); +} + +static inline uint32_t near_get_be32(const void *ptr) +{ + return near_get_unaligned((const uint32_t *) ptr); +} + +static inline uint16_t near_get_le16(const void *ptr) +{ + return bswap_16(near_get_unaligned((const uint16_t *) ptr)); +} + +static inline uint16_t near_get_be16(const void *ptr) +{ + return near_get_unaligned((const uint16_t *) ptr); +} + +static inline void near_put_le64(uint64_t val, const void *ptr) +{ + near_put_unaligned(bswap_64(val), (uint64_t *) ptr); +} + +static inline void near_put_be64(uint64_t val, const void *ptr) +{ + near_put_unaligned(val, (uint64_t *) ptr); +} + +static inline void near_put_le32(uint32_t val, const void *ptr) +{ + near_put_unaligned(bswap_32(val), (uint32_t *) ptr); +} + +static inline void near_put_be32(uint32_t val, const void *ptr) +{ + near_put_unaligned(val, (uint32_t *) ptr); +} + +static inline void near_put_le16(uint16_t val, const void *ptr) +{ + near_put_unaligned(bswap_16(val), (uint16_t *) ptr); +} + +static inline void near_put_be16(uint16_t val, const void *ptr) +{ + near_put_unaligned(val, (uint16_t *) ptr); +} +#else +#error "Unknown byte order" +#endif + #endif diff --git a/plugins/nfctype4.c b/plugins/nfctype4.c index 538630a..e275a9f 100644 --- a/plugins/nfctype4.c +++ b/plugins/nfctype4.c @@ -74,7 +74,7 @@ #define T4_ALL_ACCESS 0x00 #define T4_READ_ONLY 0xFF -#define APDU_STATUS(a) (g_ntohs(*((uint16_t *)(a)))) +#define APDU_STATUS(a) near_get_be16(a) /* Tag Type 4 version ID */ static uint8_t iso_appname_v1[] = { 0xd2, 0x76, 0x0, 0x0, 0x85, 0x01, 0x0 }; @@ -365,7 +365,7 @@ static int t4_readbin_NDEF_ID(uint8_t *resp, int length, void *data) /* Add data to the tag */ err = near_tag_add_data(cookie->adapter_idx, cookie->target_idx, NULL, - g_ntohs(*((uint16_t *)(resp + NFC_STATUS_BYTE_LEN)))); + near_get_be16(resp + NFC_STATUS_BYTE_LEN)); if (err < 0) return t4_cookie_release(err, cookie); diff --git a/plugins/snep-core.c b/plugins/snep-core.c index 2155a75..ad84296 100644 --- a/plugins/snep-core.c +++ b/plugins/snep-core.c @@ -642,8 +642,8 @@ static int snep_core_response(int fd, struct p2p_snep_put_req_data *req, /* if GET, we add the Acceptable length */ if (header.request == SNEP_REQ_GET) - *(uint32_t *)(fragment->data + SNEP_REQ_PUT_HEADER_LENGTH) = - GUINT32_TO_BE(snep_req_header_length); + near_put_be32(snep_req_header_length, + fragment->data + SNEP_REQ_PUT_HEADER_LENGTH); if (fragmenting == TRUE) { memcpy(fragment->data + snep_req_header_length, ndef->data, diff --git a/src/bluetooth.c b/src/bluetooth.c index 5c96b2e..51b659b 100644 --- a/src/bluetooth.c +++ b/src/bluetooth.c @@ -67,14 +67,6 @@ #define OOB_SP_SIZE 16 #define EIR_SIZE_MAX 255 -#define get_unaligned(ptr) \ -({ \ - struct __attribute__((packed)) { \ - typeof(*(ptr)) __v; \ - } *__p = (typeof(__p)) (ptr); \ - __p->__v; \ -}) - struct near_oob_data { char *def_adapter; @@ -641,8 +633,7 @@ int __near_bluetooth_parse_oob_record(struct bt_data *data, * the NDEF forum NDEF spec define a payload length as single * byte (and the payload size IS the oob data size). */ - bt_oob_data_size = - GUINT16_FROM_LE(get_unaligned((uint16_t *) ptr)); + bt_oob_data_size = near_get_le16(ptr); if (bt_oob_data_size > 0xFF) /* Big Endian */ bt_oob_data_size = GUINT16_FROM_BE(bt_oob_data_size); diff --git a/src/ndef.c b/src/ndef.c index fa61548..1183280 100644 --- a/src/ndef.c +++ b/src/ndef.c @@ -907,8 +907,7 @@ static struct near_ndef_record_header *parse_record_header(uint8_t *rec, rec_header->payload_len = rec[offset++]; header_len++; } else { - rec_header->payload_len = - g_ntohl(*((uint32_t *)(rec + offset))); + rec_header->payload_len = near_get_be32(rec + offset); offset += 4; header_len += 4; @@ -1260,8 +1259,7 @@ parse_sp_payload(uint8_t *payload, uint32_t length) if (rec_header->payload_len != 4) goto fail; - sp_payload->size = - g_ntohl(*((uint32_t *)(payload + offset))); + sp_payload->size = near_get_be32(payload + offset); break; case RECORD_TYPE_WKT_TYPE: @@ -1716,7 +1714,7 @@ static struct near_ndef_message *near_ndef_prepare_cr_message(uint16_t cr_id) return NULL; /* Prepare ac message */ - *(uint16_t *)(cr_msg->data + cr_msg->offset) = g_htons(cr_id); + near_put_be16(cr_id, cr_msg->data + cr_msg->offset); return cr_msg; } @@ -2177,7 +2175,8 @@ static struct near_ndef_ho_payload *parse_ho_payload(enum record_type rec_type, } ho_payload->collision_record = - g_ntohs(*((uint16_t *)(payload + offset))); + near_get_be16(payload + offset); + break; case RECORD_TYPE_WKT_ALTERNATIVE_CARRIER: @@ -2526,7 +2525,7 @@ int near_ndef_record_length(uint8_t *ndef_in, size_t ndef_in_length) if (RECORD_SR_BIT(hdr) == 1) { ndef_size += ndef_in[offset++]; } else { - ndef_size += g_ntohl(*((uint32_t *)(ndef_in + offset))); + ndef_size += near_get_be32(ndef_in + offset); offset += 4; if (offset >= ndef_in_length) diff --git a/src/tlv.c b/src/tlv.c index cc6d5a3..b6829f2 100644 --- a/src/tlv.c +++ b/src/tlv.c @@ -32,7 +32,7 @@ uint16_t near_tlv_length(uint8_t *tlv) if (tlv[0] == TLV_NULL || tlv[0] == TLV_END) length = 0; else if (tlv[1] == 0xff) - length = g_ntohs(*(uint16_t *)(tlv + 2)); + length = near_get_be16(tlv + 2); else length = tlv[1]; -- 2.7.4