diff options
author | Alex Richardson <arichardson@FreeBSD.org> | 2022-09-15 18:53:30 +0000 |
---|---|---|
committer | Simon McVittie <smcv@collabora.com> | 2022-09-21 11:35:05 +0000 |
commit | 33dbeb5ebe28aadcde9f6f6bf22eb86fa7023dfa (patch) | |
tree | 2bedf05f445f0ac071f835076882647284e80c90 /dbus | |
parent | c4a8c2d920002a961d13dab4247f91e9f2c18df6 (diff) | |
download | dbus-33dbeb5ebe28aadcde9f6f6bf22eb86fa7023dfa.tar.gz |
dbus-mempool.c: ensure that all alignments are aligned to max_align_t
This is required e.g. for CHERI-enabled targets such as Arm Morello where
aligning to sizeof(long) is not sufficient to load/store pointers (which
need 16 byte alignment instead of 8 bytes).
As we can't depend on C11 yet, this commit adds a max_align_t emulation
to dbus-internals.h.
Diffstat (limited to 'dbus')
-rw-r--r-- | dbus/dbus-internals.h | 15 | ||||
-rw-r--r-- | dbus/dbus-mempool.c | 32 |
2 files changed, 41 insertions, 6 deletions
diff --git a/dbus/dbus-internals.h b/dbus/dbus-internals.h index deee366f..4643053b 100644 --- a/dbus/dbus-internals.h +++ b/dbus/dbus-internals.h @@ -283,6 +283,21 @@ _dbus_assert_error_xor_bool (const DBusError *error, #define _DBUS_ALIGN_ADDRESS(this, boundary) \ ((void*)_DBUS_ALIGN_VALUE(this, boundary)) +#define _DBUS_IS_ALIGNED(this, boundary) \ + ((((size_t) (uintptr_t) (this)) & ((size_t) (boundary) - 1)) == 0) + +/** + * Aligning a pointer to _DBUS_ALIGNOF(dbus_max_align_t) guarantees that all + * scalar types can be loaded/stored from/to such an address without incurring + * an alignment fault (or a slow misaligned access). + * This is based on C11 max_align_t, but falls back to DBusBasicValue for + * older C standards. + */ +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) +typedef max_align_t dbus_max_align_t; +#else +typedef DBusBasicValue dbus_max_align_t; +#endif DBUS_PRIVATE_EXPORT char* _dbus_strdup (const char *str); diff --git a/dbus/dbus-mempool.c b/dbus/dbus-mempool.c index c6565351..dc0b4467 100644 --- a/dbus/dbus-mempool.c +++ b/dbus/dbus-mempool.c @@ -82,12 +82,24 @@ struct DBusMemBlock * when we free the mem pool. */ - /* this is a size_t so that "elements" is aligned */ size_t used_so_far; /**< bytes of this block already allocated as elements. */ - +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) + /* + * Ensure that elements is aligned correctly. For all supported pre-C11 + * targets, the size_t above should ensure that the elements array is + * sufficiently aligned (this is checked in the static assert below). + */ + _Alignas (dbus_max_align_t) +#endif unsigned char elements[]; /**< the block data, actually allocated to required size */ }; +_DBUS_STATIC_ASSERT (_DBUS_IS_ALIGNED (sizeof (struct DBusMemBlock), + _DBUS_ALIGNOF (dbus_max_align_t))); +_DBUS_STATIC_ASSERT (_DBUS_IS_ALIGNED (offsetof (struct DBusMemBlock, + elements), + _DBUS_ALIGNOF (dbus_max_align_t))); + /** * Internals fields of DBusMemPool */ @@ -152,10 +164,11 @@ _dbus_mem_pool_new (int element_size, _dbus_assert (element_size >= (int) sizeof (void*)); _dbus_assert (element_size >= (int) sizeof (DBusFreedElement)); - /* align the element size to a pointer boundary so we won't get bus - * errors under other architectures. + /* align the element size to be suitable for the most-aligned type + * that we care about (in practice usually a pointer). */ - pool->element_size = _DBUS_ALIGN_VALUE (element_size, sizeof (void *)); + pool->element_size = + _DBUS_ALIGN_VALUE (element_size, _DBUS_ALIGNOF (dbus_max_align_t)); pool->zero_elements = zero_elements != FALSE; @@ -239,6 +252,8 @@ _dbus_mem_pool_alloc (DBusMemPool *pool) VALGRIND_MEMPOOL_ALLOC (pool, (void *) &block->elements[0], pool->element_size); + _dbus_assert (_DBUS_IS_ALIGNED (&block->elements[0], + _DBUS_ALIGNOF (dbus_max_align_t))); return (void*) &block->elements[0]; } else @@ -264,7 +279,8 @@ _dbus_mem_pool_alloc (DBusMemPool *pool) memset (element, '\0', pool->element_size); pool->allocated_elements += 1; - + _dbus_assert ( + _DBUS_IS_ALIGNED (element, _DBUS_ALIGNOF (dbus_max_align_t))); return element; } else @@ -306,6 +322,8 @@ _dbus_mem_pool_alloc (DBusMemPool *pool) block = dbus_malloc0 (alloc_size); else block = dbus_malloc (alloc_size); + _dbus_assert ( + _DBUS_IS_ALIGNED (block, _DBUS_ALIGNOF (dbus_max_align_t))); #ifdef DBUS_ENABLE_EMBEDDED_TESTS _dbus_set_fail_alloc_counter (saved_counter); @@ -327,6 +345,8 @@ _dbus_mem_pool_alloc (DBusMemPool *pool) pool->allocated_elements += 1; VALGRIND_MEMPOOL_ALLOC (pool, element, pool->element_size); + _dbus_assert ( + _DBUS_IS_ALIGNED (element, _DBUS_ALIGNOF (dbus_max_align_t))); return element; } } |