diff options
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; } } |