From 86bdf117148388a39f5d0c24e5259314f3e29fb5 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Mon, 5 Dec 2022 23:11:13 +0100 Subject: [PATCH 1/3] fundamental: add CAST_ALIGN_PTR() macro --- src/fundamental/macro-fundamental.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/fundamental/macro-fundamental.h b/src/fundamental/macro-fundamental.h index 65c9e042cd..db778c7609 100644 --- a/src/fundamental/macro-fundamental.h +++ b/src/fundamental/macro-fundamental.h @@ -354,6 +354,16 @@ static inline size_t ALIGN_TO(size_t l, size_t ali) { ((l) + (ali) - 1) & ~((ali) - 1), \ VOID_0) +/* Similar to ((t *) (void *) (p)) to cast a pointer. The macro asserts that the pointer has a suitable + * alignment for type "t". This exists for places where otherwise "-Wcast-align=strict" would issue a + * warning or if you want to assert that the cast gives a pointer of suitable alignment. */ +#define CAST_ALIGN_PTR(t, p) \ + ({ \ + const void *_p = (p); \ + assert(((uintptr_t) _p) % __alignof__(t) == 0); \ + (t *) _p; \ + }) + #define UPDATE_FLAG(orig, flag, b) \ ((b) ? ((orig) | (flag)) : ((orig) & ~(flag))) #define SET_FLAG(v, flag, b) \ From b6256af75e0609e451198ed90c293efd50827ab3 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 8 Dec 2022 17:48:34 +0100 Subject: [PATCH 2/3] socket-util: add CMSG_TYPED_DATA() as type-safe wrapper around CMSG_DATA() --- src/basic/socket-util.h | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/basic/socket-util.h b/src/basic/socket-util.h index 2e36e1a56b..0b8d53e895 100644 --- a/src/basic/socket-util.h +++ b/src/basic/socket-util.h @@ -175,15 +175,17 @@ int flush_accept(int fd); #define CMSG_FOREACH(cmsg, mh) \ for ((cmsg) = CMSG_FIRSTHDR(mh); (cmsg); (cmsg) = CMSG_NXTHDR((mh), (cmsg))) +#define CMSG_TYPED_DATA(cmsg, type) \ + ({ \ + struct cmsghdr *_cmsg = cmsg; \ + _cmsg ? CAST_ALIGN_PTR(type, CMSG_DATA(_cmsg)) : (type*) NULL; \ + }) + struct cmsghdr* cmsg_find(struct msghdr *mh, int level, int type, socklen_t length); /* Type-safe, dereferencing version of cmsg_find() */ -#define CMSG_FIND_DATA(mh, level, type, ctype) \ - ({ \ - struct cmsghdr *_found; \ - _found = cmsg_find(mh, level, type, CMSG_LEN(sizeof(ctype))); \ - (ctype*) (_found ? CMSG_DATA(_found) : NULL); \ - }) +#define CMSG_FIND_DATA(mh, level, type, ctype) \ + CMSG_TYPED_DATA(cmsg_find(mh, level, type, CMSG_LEN(sizeof(ctype))), ctype) /* Resolves to a type that can carry cmsghdr structures. Make sure things are properly aligned, i.e. the type * itself is placed properly in memory and the size is also aligned to what's appropriate for "cmsghdr" From 6759b627201acb4dd1ab09546ef95229d0269c20 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 1 Dec 2022 14:07:22 +0100 Subject: [PATCH 3/3] all: avoid various "-Wcast-align=strict" warnings --- src/basic/fd-util.c | 3 ++- src/basic/hashmap.c | 5 +++-- src/libsystemd-network/sd-dhcp6-client.c | 2 +- src/libsystemd-network/sd-dhcp6-lease.c | 2 +- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/basic/fd-util.c b/src/basic/fd-util.c index 01a45e4384..b97039284c 100644 --- a/src/basic/fd-util.c +++ b/src/basic/fd-util.c @@ -501,7 +501,8 @@ void cmsg_close_all(struct msghdr *mh) { CMSG_FOREACH(cmsg, mh) if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) - close_many((int*) CMSG_DATA(cmsg), (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int)); + close_many(CMSG_TYPED_DATA(cmsg, int), + (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int)); } bool fdname_is_valid(const char *s) { diff --git a/src/basic/hashmap.c b/src/basic/hashmap.c index d19627595f..de7d16c397 100644 --- a/src/basic/hashmap.c +++ b/src/basic/hashmap.c @@ -373,8 +373,9 @@ static void get_hash_key(uint8_t hash_key[HASH_KEY_SIZE], bool reuse_is_ok) { } static struct hashmap_base_entry* bucket_at(HashmapBase *h, unsigned idx) { - return (struct hashmap_base_entry*) - ((uint8_t*) storage_ptr(h) + idx * hashmap_type_info[h->type].entry_size); + return CAST_ALIGN_PTR( + struct hashmap_base_entry, + (uint8_t *) storage_ptr(h) + idx * hashmap_type_info[h->type].entry_size); } static struct plain_hashmap_entry* plain_bucket_at(Hashmap *h, unsigned idx) { diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c index ee48160046..3f34b46280 100644 --- a/src/libsystemd-network/sd-dhcp6-client.c +++ b/src/libsystemd-network/sd-dhcp6-client.c @@ -1293,7 +1293,7 @@ static int client_receive_message( if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_TIMESTAMP && cmsg->cmsg_len == CMSG_LEN(sizeof(struct timeval))) - triple_timestamp_from_realtime(&t, timeval_load((struct timeval*) CMSG_DATA(cmsg))); + triple_timestamp_from_realtime(&t, timeval_load(CMSG_TYPED_DATA(cmsg, struct timeval))); } if (client->transaction_id != (message->transaction_id & htobe32(0x00ffffff))) diff --git a/src/libsystemd-network/sd-dhcp6-lease.c b/src/libsystemd-network/sd-dhcp6-lease.c index 57c23965ed..3dcccf1729 100644 --- a/src/libsystemd-network/sd-dhcp6-lease.c +++ b/src/libsystemd-network/sd-dhcp6-lease.c @@ -619,7 +619,7 @@ static int dhcp6_lease_parse_message( return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EINVAL), "Received information refresh time option with an invalid length (%zu).", optlen); - irt = unaligned_read_be32((be32_t *) optval) * USEC_PER_SEC; + irt = unaligned_read_be32(optval) * USEC_PER_SEC; break; } }