From: Arran Cudbard-Bell Date: Thu, 28 Oct 2021 16:27:46 +0000 (-0400) Subject: Use builtins for overflow detection X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f902cd727656fa78527bc0ba2c714a95b6e94b1c;p=thirdparty%2Ffreeradius-server.git Use builtins for overflow detection --- diff --git a/src/lib/util/misc.c b/src/lib/util/misc.c index b35fcd33442..8de3f3f05f7 100644 --- a/src/lib/util/misc.c +++ b/src/lib/util/misc.c @@ -513,7 +513,7 @@ int fr_size_from_str(size_t *out, char const *str) break; case 'k': /* kilobyte */ - if (fr_multiply(&size, size, 1024)) { + if (!fr_multiply(&size, size, 1024)) { overflow: fr_strerror_printf("Value must be less than %zu", (size_t)SIZE_MAX); return -1; @@ -521,15 +521,15 @@ int fr_size_from_str(size_t *out, char const *str) break; case 'm': /* megabyte */ - if (fr_multiply(&size, size, (1024 * 1024))) goto overflow; + if (!fr_multiply(&size, size, (1024 * 1024))) goto overflow; break; case 'g': /* gigabyte */ - if (fr_multiply(&size, size, (1024 * 1024 * 1024))) goto overflow; + if (!fr_multiply(&size, size, (1024 * 1024 * 1024))) goto overflow; break; case 't': /* terabyte */ - if (fr_multiply(&size, size, ((uint64_t)1024 * 1024 * 1024 * 1024))) goto overflow; + if (!fr_multiply(&size, size, ((uint64_t)1024 * 1024 * 1024 * 1024))) goto overflow; break; default: @@ -554,27 +554,6 @@ int fr_size_from_str(size_t *out, char const *str) return 0; } -/** Multiply, checking for overflow - * - * Multiplication will only occur if it would not overflow. - * - * @param[out] result of multiplication. - * @param[in] lhs First operand. - * @param[in] rhs Second operand. - * - * @return - * - true multiplication overflowed. - * - false multiplication did not overflow. - */ -bool fr_multiply(uint64_t *result, uint64_t lhs, uint64_t rhs) -{ - if (rhs > 0 && (UINT64_MAX / rhs) < lhs) return true; - - *result = lhs * rhs; /* ubsan would flag this */ - - return false; -} - /** Multiply with modulo wrap * * Avoids multiplication overflow. diff --git a/src/lib/util/misc.h b/src/lib/util/misc.h index dead5f8aece..ed8cf29636b 100644 --- a/src/lib/util/misc.h +++ b/src/lib/util/misc.h @@ -27,6 +27,39 @@ RCSIDH(misc_h, "$Id$") extern "C" { #endif +/** Multiplies two integers together + * + * @param[in] _out Where to store the result. + * @param[in] _a first argument to multiply. + * @param[in] _b second argument to multiply. + * @return + * - false on overflow. + * - true if there was no overflow. + */ +#define fr_multiply(_out, _a, _b) !__builtin_mul_overflow(_a, _b, _out) + +/** Adds two integers + * + * @param[in] _out Where to store the result. + * @param[in] _a first argument to add. + * @param[in] _b second argument to add. + * @return + * - false on overflow. + * - true if there was no overflow. + */ +#define fr_add(_out, _a, _b) !__builtin_add_overflow(_a, _b, _out) + +/** Subtraces two integers + * + * @param[in] _out Where to store the result. + * @param[in] _a first argument to subtract. + * @param[in] _b second argument to subtract. + * @return + * - false on overflow. + * - true if there was no overflow. + */ +#define fr_sub(_out, _a, _b) !__builtin_sub_overflow(_a, _b, _out) + #include #include #include @@ -200,7 +233,6 @@ ssize_t fr_writev(int fd, struct iovec vector[], int iovcnt, fr_time_delta_t ti ssize_t fr_utf8_to_ucs2(uint8_t *out, size_t outlen, char const *in, size_t inlen); size_t fr_snprint_uint128(char *out, size_t outlen, uint128_t const num); -bool fr_multiply(uint64_t *result, uint64_t lhs, uint64_t rhs); uint64_t fr_multiply_mod(uint64_t lhs, uint64_t rhs, uint64_t mod); int fr_size_from_str(size_t *out, char const *str);