]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Use builtins for overflow detection
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Thu, 28 Oct 2021 16:27:46 +0000 (12:27 -0400)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Thu, 28 Oct 2021 16:31:07 +0000 (12:31 -0400)
src/lib/util/misc.c
src/lib/util/misc.h

index b35fcd33442882386595d9b8af455b3aaa82e9d5..8de3f3f05f7298032761bc83b3a3938a591cc833 100644 (file)
@@ -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.
index dead5f8aecedd4e113c6e838651b3412c5023fd7..ed8cf29636b6a6e8e5868e09b1cfb369ddd0b017 100644 (file)
@@ -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 <freeradius-devel/build.h>
 #include <freeradius-devel/missing.h>
 #include <freeradius-devel/util/print.h>
@@ -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);