From 31b96b58e759e939f852c723218e9681dfed3cb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dan=20=C4=8Cerm=C3=A1k?= Date: Thu, 8 Mar 2018 00:32:14 +0100 Subject: [PATCH] [safe_op] improved signed int overflow checks via integer promotion The fallback signed integer overflow check is quite expensive, but the addition can be safely performed when saved in an int due to integer promotion rules. This makes the check a little less expensive. --- src/safe_op.hpp | 41 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/src/safe_op.hpp b/src/safe_op.hpp index ed3f30f4..1ac8b9a8 100644 --- a/src/safe_op.hpp +++ b/src/safe_op.hpp @@ -114,10 +114,11 @@ namespace Safe struct fallback_add_overflow; /*! - * @brief Overload of fallback_add_overflow for signed integers + * @brief Overload of fallback_add_overflow for signed integer types + * larger then int or with the same size as int */ template - struct fallback_add_overflow::VALUE>::type> + struct fallback_add_overflow::VALUE && sizeof(T) >= sizeof(int)>::type> { /*! * @brief Adds the two summands only if no overflow occurs @@ -147,6 +148,42 @@ namespace Safe } }; + /*! + * @brief Overload of fallback_add_overflow for signed integers smaller + * then int. + */ + template + struct fallback_add_overflow::VALUE && sizeof(T) < sizeof(int)>::type> + { + /*! + * @brief Adds the two summands only if no overflow occurs + * + * This function adds summand_1 and summand_2 exploiting integer + * promotion rules, thereby not causing undefined behavior. The + * result is checked against the limits of T and true is returned if + * they are exceeded. Otherwise the sum is saved in result and false + * is returned. + * + * @return true on overflow, false on no overflow + * + * The value in result is only valid when the function returns + * false. + * + * Further information: + * https://wiki.sei.cmu.edu/confluence/display/c/INT02-C.+Understand+integer+conversion+rules + */ + static bool add(T summand_1, T summand_2, T& result) + { + const int res = summand_1 + summand_2; + if ((res > std::numeric_limits::max()) || (res < std::numeric_limits::min())) { + return true; + } else { + result = static_cast(res); + return false; + } + } + }; + /*! * @brief Overload of fallback_add_overflow for unsigned integers */