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.
This commit is contained in:
Ondřej Surý
2021-10-20 11:22:52 +02:00
committed by Ondřej Surý
parent 8c05f12bc8
commit 2b147ac358
2 changed files with 31 additions and 7 deletions

View File

@@ -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 <limits.h>]],
[[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?

View File

@@ -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) {