From aac5f4514f71d04ac3dcb8b923209781895d7ff2 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Tue, 10 Feb 2015 10:41:47 -0200 Subject: [PATCH] shared: add helper function to add and check for overflow Use _builtin_uaddll_overflow/_builtin_uaddl_overflow when available, abstracting the type to use it with uint64_t. Otherwise fallback to the implementation as added in 67466f2 ("Prevent offset + size overflow."). This also adds the tests for this new helper in the testsuite. --- configure.ac | 2 ++ m4/attributes.m4 | 2 ++ shared/util.h | 16 ++++++++++++++++ testsuite/test-util.c | 19 +++++++++++++++++++ 4 files changed, 39 insertions(+) diff --git a/configure.ac b/configure.ac index 30eea861..30eb37f7 100644 --- a/configure.ac +++ b/configure.ac @@ -49,6 +49,8 @@ AC_CHECK_FUNCS_ONCE([finit_module]) CC_CHECK_FUNC_BUILTIN([__builtin_clz]) CC_CHECK_FUNC_BUILTIN([__builtin_types_compatible_p]) +CC_CHECK_FUNC_BUILTIN([__builtin_uaddl_overflow], [ ], [ ]) +CC_CHECK_FUNC_BUILTIN([__builtin_uaddll_overflow], [ ], [ ]) # dietlibc doesn't have st.st_mtim struct member AC_CHECK_MEMBERS([struct stat.st_mtim], [], [], [#include ]) diff --git a/m4/attributes.m4 b/m4/attributes.m4 index 79227460..985a3ed0 100644 --- a/m4/attributes.m4 +++ b/m4/attributes.m4 @@ -262,6 +262,8 @@ AC_DEFUN([CC_CHECK_FUNC_BUILTIN], [ m4_case([$1], [__builtin_clz], [$1(0)], [__builtin_types_compatible_p], [$1(int, int)], + [__builtin_uaddl_overflow], [$1(0UL, 0UL, (void*)0)], + [__builtin_uaddll_overflow], [$1(0ULL, 0ULL, (void*)0)], [__builtin_expect], [$1(0, 0)] )])], [cc_cv_have_$1=yes], diff --git a/shared/util.h b/shared/util.h index 4c59705a..6f602d3a 100644 --- a/shared/util.h +++ b/shared/util.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -72,3 +73,18 @@ static inline void freep(void *p) { free(*(void**) p); } #define _cleanup_free_ _cleanup_(freep) + +static inline bool addu64_overflow(uint64_t a, uint64_t b, uint64_t *res) +{ +#if (HAVE___BUILTIN_UADDL_OVERFLOW && HAVE___BUILTIN_UADDLL_OVERFLOW) +#if __SIZEOF_LONG__ == 8 + return __builtin_uaddl_overflow(a, b, res); +#elif __SIZEOF_LONG_LONG__ == 8 + return __builtin_uaddll_overflow(a, b, res); +#else +#error "sizeof(long long) != 8" +#endif +#endif + *res = a + b; + return ULLONG_MAX - a < b; +} diff --git a/testsuite/test-util.c b/testsuite/test-util.c index b0c4ce6c..5e25e587 100644 --- a/testsuite/test-util.c +++ b/testsuite/test-util.c @@ -206,5 +206,24 @@ DEFINE_TEST(test_write_str_safe, }, }); +static int test_addu64_overflow(const struct test *t) +{ + uint64_t res; + bool overflow; + + overflow = addu64_overflow(UINT64_MAX - 1, 1, &res); + assert_return(!overflow, EXIT_FAILURE); + assert_return(res == UINT64_MAX, EXIT_FAILURE); + + overflow = addu64_overflow(UINT64_MAX, 1, &res); + assert_return(overflow, EXIT_FAILURE); + + return EXIT_SUCCESS; +} +DEFINE_TEST(test_addu64_overflow, + .description = "check implementation of addu4_overflow()", + .need_spawn = false, + ); + TESTSUITE_MAIN(); -- 2.47.2