]> git.ipfire.org Git - thirdparty/kmod.git/commitdiff
shared: introduce umul{32,64}_overflow() helpers
authorEmil Velikov <emil.l.velikov@gmail.com>
Mon, 30 Sep 2024 20:35:18 +0000 (21:35 +0100)
committerLucas De Marchi <lucas.de.marchi@gmail.com>
Tue, 15 Oct 2024 17:42:56 +0000 (12:42 -0500)
We'll use them to implement the size_t variant.

Signed-off-by: Emil Velikov <emil.l.velikov@gmail.com>
Link: https://github.com/kmod-project/kmod/pull/169
[ Fixup commit message for renamed functions ]
Signed-off-by: Lucas De Marchi <lucas.de.marchi@gmail.com>
meson.build
shared/util.h
testsuite/test-util.c

index eb5cfadd76271db350cec5b8783c8cd066d84165..0da69bd5322645fb19ae5c1456baee4f82656ea7 100644 (file)
@@ -52,6 +52,9 @@ _builtins = [
   ['__builtin_uadd_overflow', '0U, 0U, (void*)0', false],
   ['__builtin_uaddl_overflow', '0UL, 0UL, (void*)0', false],
   ['__builtin_uaddll_overflow', '0ULL, 0ULL, (void*)0', false],
+  ['__builtin_umul_overflow', '0U, 0U, (void*)0', false],
+  ['__builtin_umull_overflow', '0UL, 0UL, (void*)0', false],
+  ['__builtin_umulll_overflow', '0ULL, 0ULL, (void*)0', false],
 ]
 foreach tuple : _builtins
   builtin = tuple[0]
index 87c7279611e06ab8d744bd8b3c0bfed5708c55ce..7045e65b4f6eae70e4821060a7b73a66514d47d6 100644 (file)
@@ -113,3 +113,25 @@ static inline bool uadd64_overflow(uint64_t a, uint64_t b, uint64_t *res)
        return UINT64_MAX - a < b;
 #endif
 }
+
+static inline bool umul32_overflow(uint32_t a, uint32_t b, uint32_t *res)
+{
+#if (HAVE___BUILTIN_UMUL_OVERFLOW && __SIZEOF_INT__ == 4)
+       return __builtin_umul_overflow(a, b, res);
+#else
+       *res = a * b;
+       return UINT32_MAX / a < b;
+#endif
+}
+
+static inline bool umul64_overflow(uint64_t a, uint64_t b, uint64_t *res)
+{
+#if (HAVE___BUILTIN_UMULL_OVERFLOW && __SIZEOF_LONG__ == 8)
+       return __builtin_umull_overflow(a, b, res);
+#elif (HAVE___BUILTIN_UMULLL_OVERFLOW && __SIZEOF_LONG_LONG__ == 8)
+       return __builtin_umulll_overflow(a, b, res);
+#else
+       *res = a * b;
+       return UINT64_MAX / a < b;
+#endif
+}
index 1f968606eecdf57d350eb8c5244b93341cce5f9d..e38b9f833f6fafd783a01aa87c5f4ddd2eb7ad1b 100644 (file)
@@ -225,6 +225,40 @@ static int test_uadd64_overflow(const struct test *t)
 DEFINE_TEST(test_uadd64_overflow,
            .description = "check implementation of uadd64_overflow()")
 
+static int test_umul32_overflow(const struct test *t)
+{
+       uint32_t res;
+       bool overflow;
+
+       overflow = umul32_overflow(UINT32_MAX / 0x10, 0x10, &res);
+       assert_return(!overflow, EXIT_FAILURE);
+       assert_return(res == (UINT32_MAX & ~0xf), EXIT_FAILURE);
+
+       overflow = umul32_overflow(UINT32_MAX, 0x10, &res);
+       assert_return(overflow, EXIT_FAILURE);
+
+       return EXIT_SUCCESS;
+}
+DEFINE_TEST(test_umul32_overflow,
+           .description = "check implementation of umul32_overflow()")
+
+static int test_umul64_overflow(const struct test *t)
+{
+       uint64_t res;
+       bool overflow;
+
+       overflow = umul64_overflow(UINT64_MAX / 0x10, 0x10, &res);
+       assert_return(!overflow, EXIT_FAILURE);
+       assert_return(res == (UINT64_MAX & ~0xf), EXIT_FAILURE);
+
+       overflow = umul64_overflow(UINT64_MAX, 0x10, &res);
+       assert_return(overflow, EXIT_FAILURE);
+
+       return EXIT_SUCCESS;
+}
+DEFINE_TEST(test_umul64_overflow,
+           .description = "check implementation of umul64_overflow()")
+
 static int test_backoff_time(const struct test *t)
 {
        unsigned long long delta = 0;