build fix
[LibreOffice.git] / include / o3tl / safeint.hxx
blob5ebf353b6bd61d3e9bab332ca31f772bed67ac6e
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
10 #ifndef INCLUDED_O3TL_SAFEINT_HXX
11 #define INCLUDED_O3TL_SAFEINT_HXX
13 #include <limits>
14 #if defined(_MSC_VER)
15 #include <safeint.h>
16 #else
17 #ifndef __has_builtin
18 # define __has_builtin(x) 0
19 #endif
20 #endif
22 namespace o3tl
25 #if defined(_MSC_VER)
27 template<typename T> inline bool checked_multiply(T a, T b, T& result)
29 return !msl::utilities::SafeMultiply(a, b, result);
32 template<typename T> inline bool checked_add(T a, T b, T& result)
34 return !msl::utilities::SafeAdd(a, b, result);
37 #elif (defined __GNUC__ && __GNUC__ >= 5) || (__has_builtin(__builtin_mul_overflow) && !(defined ANDROID && defined __clang__))
39 template<typename T> inline bool checked_multiply(T a, T b, T& result)
41 return __builtin_mul_overflow(a, b, &result);
44 template<typename T> inline bool checked_add(T a, T b, T& result)
46 return __builtin_add_overflow(a, b, &result);
49 #else
51 //https://www.securecoding.cert.org/confluence/display/c/INT32-C.+Ensure+that+operations+on+signed+integers+do+not+result+in+overflow
52 template<typename T> inline typename std::enable_if<std::is_signed<T>::value, bool>::type checked_multiply(T a, T b, T& result)
54 if (a > 0) { /* a is positive */
55 if (b > 0) { /* a and b are positive */
56 if (a > (std::numeric_limits<T>::max() / b)) {
57 return true; /* Handle error */
59 } else { /* a positive, b nonpositive */
60 if (b < (std::numeric_limits<T>::min() / a)) {
61 return true; /* Handle error */
63 } /* a positive, b nonpositive */
64 } else { /* a is nonpositive */
65 if (b > 0) { /* a is nonpositive, b is positive */
66 if (a < (std::numeric_limits<T>::min() / b)) {
67 return true; /* Handle error */
69 } else { /* a and b are nonpositive */
70 if ( (a != 0) && (b < (std::numeric_limits<T>::max() / a))) {
71 return true; /* Handle error */
73 } /* End if a and b are nonpositive */
74 } /* End if a is nonpositive */
76 result = a * b;
78 return false;
81 //https://www.securecoding.cert.org/confluence/display/c/INT30-C.+Ensure+that+unsigned+integer+operations+do+not+wrap
82 template<typename T> inline typename std::enable_if<std::is_unsigned<T>::value, bool>::type checked_multiply(T a, T b, T& result)
84 if (b && a > std::numeric_limits<T>::max() / b) {
85 return true;/* Handle error */
88 result = a * b;
90 return false;
93 //https://www.securecoding.cert.org/confluence/display/c/INT32-C.+Ensure+that+operations+on+signed+integers+do+not+result+in+overflow
94 template<typename T> inline typename std::enable_if<std::is_signed<T>::value, bool>::type checked_add(T a, T b, T& result)
96 if (((b > 0) && (a > (std::numeric_limits<T>::max() - b))) ||
97 ((b < 0) && (a < (std::numeric_limits<T>::min() - b)))) {
98 return true;
101 result = a + b;
103 return false;
106 //https://www.securecoding.cert.org/confluence/display/c/INT30-C.+Ensure+that+unsigned+integer+operations+do+not+wrap
107 template<typename T> inline typename std::enable_if<std::is_unsigned<T>::value, bool>::type checked_add(T a, T b, T& result)
109 if (std::numeric_limits<T>::max() - a < b) {
110 return true;/* Handle error */
113 result = a + b;
115 return false;
118 #endif
122 #endif
124 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */