From 2b147ac35860dcacf096d2caca9bd855a0e04bc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= Date: Wed, 20 Oct 2021 11:22:52 +0200 Subject: [PATCH] Use __builtin_*_overflow for isc_time_{add,subtract}() Use the __builtin_uadd_overflow() and __builtin_usub_overflow() for overflow checks in isc_time_add() and isc_time_subtract(). This generates more efficient and safe code. --- configure.ac | 26 +++++++++++++++++++------- lib/isc/time.c | 12 ++++++++++++ 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/configure.ac b/configure.ac index a3b54cbd71..d17d8f20b2 100644 --- a/configure.ac +++ b/configure.ac @@ -1164,14 +1164,26 @@ AC_LINK_IFELSE( [[]], [[return (__builtin_clz(0xff) == 24 ? 1 : 0);]] )], - [have_builtin_clz=yes - AC_MSG_RESULT(yes)], - [have_builtin_clz=no - AC_MSG_RESULT(no)] + [AC_MSG_RESULT([yes]) + AC_DEFINE(HAVE_BUILTIN_CLZ, 1, [Define to 1 if the compiler supports __builtin_clz.]) + ], + [AC_MSG_RESULT([no])] ) -if test "yes" = "$have_builtin_clz"; then - AC_DEFINE(HAVE_BUILTIN_CLZ, 1, [Define to 1 if the compiler supports __builtin_clz.]) -fi + +# +# Check for __builtin_uadd_overflow +# +AC_MSG_CHECKING([compiler support for __builtin_*_overflow()]) +AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[#include ]], + [[return (__builtin_uadd_overflow(UINT_MAX, UINT_MAX, &(unsigned int){ 0 }));]] + )], + [AC_MSG_RESULT([yes]) + AC_DEFINE([HAVE_BUILTIN_OVERFLOW], [1], [define if the compiler supports __builtin_*_overflow().]) + ], + [AC_MSG_RESULT([no]) + ]) # # Activate "rrset-order fixed" or not? diff --git a/lib/isc/time.c b/lib/isc/time.c index 76b74a81ab..77ac0da28f 100644 --- a/lib/isc/time.c +++ b/lib/isc/time.c @@ -231,10 +231,16 @@ isc_time_add(const isc_time_t *t, const isc_interval_t *i, isc_time_t *result) { REQUIRE(t->nanoseconds < NS_PER_S && i->nanoseconds < NS_PER_S); /* Seconds */ +#if HAVE_BUILTIN_OVERFLOW + if (__builtin_uadd_overflow(t->seconds, i->seconds, &result->seconds)) { + return (ISC_R_RANGE); + } +#else if (t->seconds > UINT_MAX - i->seconds) { return (ISC_R_RANGE); } result->seconds = t->seconds + i->seconds; +#endif /* Nanoseconds */ result->nanoseconds = t->nanoseconds + i->nanoseconds; @@ -256,10 +262,16 @@ isc_time_subtract(const isc_time_t *t, const isc_interval_t *i, REQUIRE(t->nanoseconds < NS_PER_S && i->nanoseconds < NS_PER_S); /* Seconds */ +#if HAVE_BUILTIN_OVERFLOW + if (__builtin_usub_overflow(t->seconds, i->seconds, &result->seconds)) { + return (ISC_R_RANGE); + } +#else if (t->seconds < i->seconds) { return (ISC_R_RANGE); } result->seconds = t->seconds - i->seconds; +#endif /* Nanoseconds */ if (t->nanoseconds >= i->nanoseconds) {