]> git.ipfire.org Git - thirdparty/kmod.git/commitdiff
shared: add helper function to add and check for overflow
authorLucas De Marchi <lucas.demarchi@intel.com>
Tue, 10 Feb 2015 12:41:47 +0000 (10:41 -0200)
committerLucas De Marchi <lucas.demarchi@intel.com>
Tue, 10 Feb 2015 12:43:44 +0000 (10:43 -0200)
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
m4/attributes.m4
shared/util.h
testsuite/test-util.c

index 30eea86153e7137d3259f46264b7f25ff40b66cb..30eb37f7f2146c9d9eace17b15ad0f47fbdd1b9e 100644 (file)
@@ -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 <sys/stat.h>])
index 79227460e2d1d90741e776f71b1eff49aaab48cf..985a3ed0bf7f95622b56a41e48db241659aaaa29 100644 (file)
@@ -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],
index 4c59705af61ab9195798db5b98dbfee21981f282..6f602d3ad21bb04be1a0d7d8927338a018e6ea4f 100644 (file)
@@ -1,5 +1,6 @@
 #pragma once
 
+#include <inttypes.h>
 #include <limits.h>
 #include <stdbool.h>
 #include <stdlib.h>
@@ -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;
+}
index b0c4ce6c8dca7919c4e588fbb523569e63a50071..5e25e587d69bdc4e0dd8f00f37bfb3405f770e3f 100644 (file)
@@ -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();