From 7eba0cd2cb79d27d93917d85300c27da23c3f54e Mon Sep 17 00:00:00 2001 From: Emil Velikov Date: Mon, 30 Sep 2024 21:35:18 +0100 Subject: [PATCH] shared: introduce umul{32,64}_overflow() helpers We'll use them to implement the size_t variant. Signed-off-by: Emil Velikov Link: https://github.com/kmod-project/kmod/pull/169 [ Fixup commit message for renamed functions ] Signed-off-by: Lucas De Marchi --- meson.build | 3 +++ shared/util.h | 22 ++++++++++++++++++++++ testsuite/test-util.c | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+) diff --git a/meson.build b/meson.build index eb5cfadd..0da69bd5 100644 --- a/meson.build +++ b/meson.build @@ -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] diff --git a/shared/util.h b/shared/util.h index 87c72796..7045e65b 100644 --- a/shared/util.h +++ b/shared/util.h @@ -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 +} diff --git a/testsuite/test-util.c b/testsuite/test-util.c index 1f968606..e38b9f83 100644 --- a/testsuite/test-util.c +++ b/testsuite/test-util.c @@ -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; -- 2.47.2