summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/config.h12
-rw-r--r--tests/bfstd.c1
2 files changed, 12 insertions, 1 deletions
diff --git a/src/config.h b/src/config.h
index c6dcc1e..b2c58be 100644
--- a/src/config.h
+++ b/src/config.h
@@ -162,7 +162,17 @@ static inline size_t align_ceil(size_t align, size_t size) {
flex_sizeof_impl(alignof(type), sizeof(type), offsetof(type, member), sizeof(((type *)NULL)->member[0]), count)
static inline size_t flex_sizeof_impl(size_t align, size_t min, size_t offset, size_t size, size_t count) {
- size_t ret = align_ceil(align, offset + size * count);
+ size_t ret = size * count;
+ size_t overflow = ret / size != count;
+
+ ret += offset;
+ overflow |= ret < offset;
+
+ size_t mask = align - 1;
+ ret += mask;
+ overflow |= ret < mask;
+ ret &= ~mask;
+ ret |= -overflow;
// 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 c6a9e9f..1917a53 100644
--- a/tests/bfstd.c
+++ b/tests/bfstd.c
@@ -41,6 +41,7 @@ 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_impl(8, 16, 4, 4, 1) == 16);
// From man 3p basename