diff options
author | Tavian Barnes <tavianator@tavianator.com> | 2023-05-11 13:08:43 -0400 |
---|---|---|
committer | Tavian Barnes <tavianator@tavianator.com> | 2023-05-11 13:14:13 -0400 |
commit | a7932050f65844fb1f1145fee87c72aadaf4f995 (patch) | |
tree | 7284a1d82b06f590df85affc9a3f96d6e13ac0a6 | |
parent | 7e26443627926bb3bcc88bd790190d5e4e0eda98 (diff) | |
download | bfs-a7932050f65844fb1f1145fee87c72aadaf4f995.tar.xz |
config: Saturate on overflow in flex_sizeof()
-rw-r--r-- | src/config.h | 12 | ||||
-rw-r--r-- | tests/bfstd.c | 1 |
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 |