From 8706515d905038ee7d869ab5ace0471c781d2624 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Tue, 16 May 2023 11:37:53 -0400 Subject: config: Align after saturating in flex_sizeof() This ensures that it's legal to call aligned_alloc() with the result, which requires a multiple of the alignment. --- src/config.h | 11 +++++++++-- tests/bfstd.c | 3 ++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/config.h b/src/config.h index b2c58be..47aa529 100644 --- a/src/config.h +++ b/src/config.h @@ -140,11 +140,18 @@ */ #define countof(array) (sizeof(array) / sizeof(0[array])) +/** + * Round down to a multiple of an alignment. + */ +static inline size_t align_floor(size_t align, size_t size) { + return size & ~(align - 1); +} + /** * Round up to a multiple of an alignment. */ static inline size_t align_ceil(size_t align, size_t size) { - return (size + align - 1) & ~(align - 1); + return align_floor(align, size + align - 1); } /** @@ -171,8 +178,8 @@ static inline size_t flex_sizeof_impl(size_t align, size_t min, size_t offset, s size_t mask = align - 1; ret += mask; overflow |= ret < mask; - ret &= ~mask; ret |= -overflow; + ret &= ~mask; // Make sure flex_sizeof(type, member, 0) >= sizeof(type), even if the // type has more padding than necessary for alignment diff --git a/tests/bfstd.c b/tests/bfstd.c index 1917a53..a986a23 100644 --- a/tests/bfstd.c +++ b/tests/bfstd.c @@ -41,7 +41,8 @@ int main(void) { }; assert(flex_sizeof(struct flexible, bar, 0) >= sizeof(struct flexible)); assert(flex_sizeof(struct flexible, bar, 16) % alignof(struct flexible) == 0); - assert(flex_sizeof(struct flexible, bar, SIZE_MAX / sizeof(int) + 1) == SIZE_MAX); + assert(flex_sizeof(struct flexible, bar, SIZE_MAX / sizeof(int) + 1) + == align_floor(alignof(struct flexible), SIZE_MAX)); assert(flex_sizeof_impl(8, 16, 4, 4, 1) == 16); // From man 3p basename -- cgit v1.2.3