fundamental: Add overflow-safe math helpers

ADD_SAFE/SUB_SAFE/MUL_SAFE do addition/subtraction/multiplication
respectively with an overflow check. If an overflow occurs these return
false, otherwise true. Example: (c = a + b) would become ADD_SAFE(&c, a,
b)

INC_SAFE/DEC_SAFE/MUL_ASSIGN_SAFE are like above but they also reassign
the first argument. Example: (a += b) would become INC_SAFE(&a, b)
This commit is contained in:
Adrian Vovk
2024-01-17 14:48:45 -05:00
parent 6d55e3a364
commit a7a67dfd9d
6 changed files with 179 additions and 8 deletions

View File

@@ -2288,7 +2288,7 @@ static EFI_STATUS initrd_prepare(
continue;
size_t new_size, read_size = info->FileSize;
if (__builtin_add_overflow(size, read_size, &new_size))
if (!ADD_SAFE(&new_size, size, read_size))
return EFI_OUT_OF_RESOURCES;
initrd = xrealloc(initrd, size, new_size);

View File

@@ -372,9 +372,9 @@ bool efi_fnmatch(const char16_t *pattern, const char16_t *haystack) {
\
uint64_t u = 0; \
while (*s >= '0' && *s <= '9') { \
if (__builtin_mul_overflow(u, 10, &u)) \
if (!MUL_ASSIGN_SAFE(&u, 10)) \
return false; \
if (__builtin_add_overflow(u, *s - '0', &u)) \
if (!INC_SAFE(&u, *s - '0')) \
return false; \
s++; \
} \
@@ -593,13 +593,13 @@ typedef struct {
static void grow_buf(FormatContext *ctx, size_t need) {
assert(ctx);
assert_se(!__builtin_add_overflow(ctx->n, need, &need));
assert_se(INC_SAFE(&need, ctx->n));
if (need < ctx->n_buf)
return;
/* Greedily allocate if we can. */
if (__builtin_mul_overflow(need, 2, &ctx->n_buf))
if (!MUL_SAFE(&ctx->n_buf, need, 2))
ctx->n_buf = need;
/* We cannot use realloc here as ctx->buf may be ctx->stack_buf, which we cannot free. */

View File

@@ -37,7 +37,7 @@ static inline void *xmalloc(size_t size) {
_malloc_ _alloc_(1, 2) _returns_nonnull_ _warn_unused_result_
static inline void *xmalloc_multiply(size_t n, size_t size) {
assert_se(!__builtin_mul_overflow(size, n, &size));
assert_se(MUL_ASSIGN_SAFE(&size, n));
return xmalloc(size);
}