Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-08-06 08:48:41

0001 // Licensed under the MIT License.
0002 // Copyright David LeBlanc - dcl@dleblanc.net
0003 
0004 /*-----------------------------------------------------------------------------------------------------------
0005 c_safe_math
0006 Version 1.0 - 6/21/22
0007 
0008 This header implements a set of functions that check for integer overflows in C code.
0009 It is based on code and logic from SafeInt.hpp, but ported to C.
0010 
0011 Portions copied from SafeInt.hpp are Licensed under the MIT License,
0012 and are originally copyrighted to Microsoft.
0013 */
0014 
0015 #ifndef C_SAFE_MATH_IMPL
0016 #define C_SAFE_MATH_IMPL
0017 
0018 #if defined _MSC_VER
0019 // static inline expansion warnings
0020 #pragma warning(disable:4710 4711)
0021 #endif
0022 
0023 #ifdef __cplusplus
0024 extern "C"
0025 {
0026 #endif
0027 
0028     // It is a bit tricky to sort out what compiler we are actually using,
0029     // do this once here, and avoid cluttering the code
0030 #define VISUAL_STUDIO_COMPILER 0
0031 #define CLANG_COMPILER 1
0032 #define GCC_COMPILER 2
0033 #define UNKNOWN_COMPILER -1
0034 
0035 // Clang will sometimes pretend to be Visual Studio
0036 // and does pretend to be gcc. Check it first, as nothing else pretends to be clang
0037 #if defined __clang__
0038 #define SAFEINT_COMPILER CLANG_COMPILER
0039 #elif defined __GNUC__
0040 #define SAFEINT_COMPILER GCC_COMPILER
0041 #elif defined _MSC_VER
0042 #define SAFEINT_COMPILER VISUAL_STUDIO_COMPILER
0043 #else
0044 #define SAFEINT_COMPILER UNKNOWN_COMPILER
0045 #endif
0046 
0047 // Various defines to help make working with multiple compilers easier - from SafeInt.hpp
0048 #if SAFEINT_COMPILER == GCC_COMPILER || SAFEINT_COMPILER == CLANG_COMPILER
0049 #define SAFEINT_NORETURN __attribute__((noreturn))
0050 #define SAFEINT_STDCALL
0051 #define SAFEINT_VISIBLE __attribute__ ((__visibility__("default")))
0052 #define SAFEINT_WEAK __attribute__ ((weak))
0053 #else
0054 #define SAFEINT_NORETURN __declspec(noreturn)
0055 #define SAFEINT_STDCALL __stdcall
0056 #define SAFEINT_VISIBLE
0057 #define SAFEINT_WEAK
0058 #endif
0059 
0060 #if SAFEINT_COMPILER == VISUAL_STUDIO_COMPILER
0061     // limits.h checks __STDC_WANT_SECURE_LIB__, but doesn't include what sets it
0062 #if !defined __STDC_WANT_SECURE_LIB__
0063 #define __STDC_WANT_SECURE_LIB__ 0
0064 #endif
0065 
0066 #endif
0067 
0068 #include <stdint.h>
0069 #include <stdbool.h>
0070 #include <limits.h>
0071 
0072 // Figure out if we should use intrinsics
0073 // If the user has already decided, let that override
0074 #define SAFEINT_MULTIPLY_MATH        0 // no intrinsics, no built in, no 128-bit
0075 #define SAFEINT_MULTIPLY_INTRINSICS  1 // 64-bit Visual Studio
0076 #define SAFEINT_MULTIPLY_BUILTIN     2 // gcc, clang
0077 #define SAFEINT_MULTIPLY_INT128      3 // Best case
0078 
0079 // We might have 128-bit int support, check for that, as it should work best
0080 #if !defined SAFEINT_HAS_INT128
0081 
0082 #if defined __SIZEOF_INT128__ && __SIZEOF_INT128__ == 16
0083 #define SAFEINT_HAS_INT128 1
0084 #else
0085 #define SAFEINT_HAS_INT128 0
0086 #endif
0087 
0088 #endif
0089 
0090 #if SAFEINT_HAS_INT128
0091 #define SAFEINT_MULTIPLY_METHOD SAFEINT_MULTIPLY_INT128
0092 #else
0093 
0094 #if !defined SAFEINT_USE_INTRINSICS
0095 // If it is the Visual Studio compiler, then it has to be 64-bit, and not ARM64EC
0096 #if SAFEINT_COMPILER == VISUAL_STUDIO_COMPILER
0097 #if defined _M_AMD64 && !defined _M_ARM64EC
0098 #include <intrin.h>
0099 #define SAFEINT_MULTIPLY_METHOD SAFEINT_MULTIPLY_INTRINSICS
0100 #else
0101 #define SAFEINT_MULTIPLY_METHOD SAFEINT_MULTIPLY_MATH
0102 #endif
0103 
0104 #else // Not VISUAL_STUDIO_COMPILER
0105 
0106     // Else for gcc and clang, we can use builtin functions
0107 #if SAFEINT_COMPILER == CLANG_COMPILER || SAFEINT_COMPILER == GCC_COMPILER
0108 #define SAFEINT_MULTIPLY_METHOD SAFEINT_MULTIPLY_BUILTIN
0109 #else
0110 #define SAFEINT_MULTIPLY_METHOD SAFEINT_MULTIPLY_MATH
0111 #endif
0112 #endif
0113 
0114 #endif // SAFEINT_USE_INTRINSICS
0115 #endif // SAFEINT_HAS_INT128
0116 
0117 /*
0118     To replace safe_math_fail, wrap this header,
0119     implement safe_math_fail how you prefer,
0120     and set SAFE_MATH_FAIL_DEFINED
0121 */
0122 
0123 #if !defined SAFE_MATH_FAIL_DEFINED
0124 #define SAFE_MATH_FAIL_DEFINED
0125 #include <stdlib.h>
0126 
0127 SAFEINT_NORETURN
0128 static inline void safe_math_fail(const char* msg)
0129 {
0130     (void)msg;
0131     abort();
0132 }
0133 #endif
0134 
0135 #if !defined UINT64_MAX
0136 
0137 #define INT8_MIN         (-127i8 - 1)
0138 #define INT16_MIN        (-32767i16 - 1)
0139 #define INT32_MIN        (-2147483647i32 - 1)
0140 #define INT64_MIN        (-9223372036854775807i64 - 1)
0141 #define INT8_MAX         127i8
0142 #define INT16_MAX        32767i16
0143 #define INT32_MAX        2147483647i32
0144 #define INT64_MAX        9223372036854775807i64
0145 #define UINT8_MAX        0xffui8
0146 #define UINT16_MAX       0xffffui16
0147 #define UINT32_MAX       0xffffffffui32
0148 #define UINT64_MAX       0xffffffffffffffffui64
0149 
0150 #endif
0151 
0152 // Utility functions
0153 
0154 // Purpose of this is to negate an int in a way
0155 // where the compiler won't remove it if the input is a 
0156 // compile time constant MIN_INT
0157 static inline int32_t negate32(int32_t in) { return (int32_t)(~(uint32_t)in + 1); }
0158 static inline int64_t negate64(int64_t in) { return (int64_t)(~(uint64_t)in + 1); }
0159 
0160 static inline uint32_t safe_abs32(int32_t in)
0161 {
0162     if (in < 0)
0163         return ~(uint32_t)in + 1;
0164 
0165     return (uint32_t)in;
0166 }
0167 
0168 static inline uint64_t safe_abs64(int64_t in)
0169 {
0170     if (in < 0)
0171         return ~(uint64_t)in + 1;
0172 
0173     return (uint64_t)in;
0174 }
0175 
0176 // Checked casting functions
0177 // 0 if the cast is safe, non-zero if unsafe
0178 static inline int check_cast_int8_int32(int32_t in) { return (in < INT8_MIN || in > INT8_MAX); }
0179 static inline int check_cast_int8_uint32(uint32_t in) { return in > INT8_MAX; }
0180 static inline int check_cast_int8_int64(int64_t in) { return in < INT8_MIN || in > INT8_MAX; }
0181 static inline int check_cast_int8_uint64(uint64_t in) { return (in > INT8_MAX); }
0182 static inline int check_cast_int16_int32(int32_t in) { return in < INT16_MIN || in > INT16_MAX; }
0183 static inline int check_cast_int16_uint32(uint32_t in) { return (in > INT16_MAX); }
0184 static inline int check_cast_int16_int64(int64_t in) { return (in < INT16_MIN || in > INT16_MAX); }
0185 static inline int check_cast_int16_uint64(uint64_t in) { return (in > INT16_MAX); }
0186 static inline int check_cast_int32_uint32(uint32_t in) { return (in > INT32_MAX); }
0187 static inline int check_cast_int32_int64(int64_t in) { return (in < INT32_MIN || in > INT32_MAX); }
0188 static inline int check_cast_int32_uint64(uint64_t in) { return (in > INT32_MAX); }
0189 static inline int check_cast_int64_uint64(uint64_t in) { return (in > INT64_MAX); }
0190 static inline int check_cast_uint8_int32(int32_t in) { return (in < 0 || in > UINT8_MAX); }
0191 static inline int check_cast_uint8_uint32(uint32_t in) { return (in > UINT8_MAX); }
0192 static inline int check_cast_uint8_int64(int64_t in) { return (in < 0 || in > UINT8_MAX); }
0193 static inline int check_cast_uint8_uint64(uint64_t in) { return (in > UINT8_MAX); }
0194 static inline int check_cast_uint16_int32(int32_t in) { return (in < 0 || in > UINT16_MAX); }
0195 static inline int check_cast_uint16_uint32(uint32_t in) { return (in > UINT16_MAX); }
0196 static inline int check_cast_uint16_int64(int64_t in) { return (in < 0 || in > UINT16_MAX); }
0197 static inline int check_cast_uint16_uint64(uint64_t in) { return (in > UINT16_MAX); }
0198 static inline int check_cast_uint32_int32(int32_t in) { return (in < 0); }
0199 static inline int check_cast_uint32_int64(int64_t in) { return (in < 0 || in > UINT32_MAX); }
0200 static inline int check_cast_uint32_uint64(uint64_t in) { return (in > UINT32_MAX); }
0201 static inline int check_cast_uint64_int64(int64_t in) { return (in < 0); }
0202 
0203 static inline int8_t safe_cast_int8_int32(int32_t in)
0204 {
0205     if (!check_cast_int8_int32(in))
0206         safe_math_fail("safe_math_fail safe_cast_int8_int32");
0207 
0208     return (int8_t)in;
0209 }
0210 
0211 static inline int8_t safe_cast_int8_uint32(uint32_t in)
0212 {
0213     if (check_cast_int8_uint32(in))
0214         safe_math_fail("safe_math_fail safe_cast_int8_uint32");
0215 
0216     return (int8_t)in;
0217 }
0218 
0219 static inline int8_t safe_cast_int8_int64(int64_t in)
0220 {
0221     if (check_cast_int8_int64(in))
0222         safe_math_fail("safe_math_fail safe_cast_int8_int64");
0223 
0224     return (int8_t)in;
0225 }
0226 
0227 static inline int8_t safe_cast_int8_uint64(uint64_t in)
0228 {
0229     if (check_cast_int8_uint64(in))
0230         safe_math_fail("safe_math_fail safe_cast_int8_uint64");
0231 
0232     return (int8_t)in;
0233 }
0234 
0235 static inline int16_t safe_cast_int16_int32(int32_t in)
0236 {
0237     if (check_cast_int16_int32(in))
0238         safe_math_fail("safe_math_fail safe_cast_int16_int32");
0239 
0240     return (int16_t)in;
0241 }
0242 
0243 static inline int16_t safe_cast_int16_uint32(uint32_t in)
0244 {
0245     if (check_cast_int16_uint32(in))
0246         safe_math_fail("safe_math_fail safe_cast_int16_uint32");
0247 
0248     return (int16_t)in;
0249 }
0250 
0251 static inline int16_t safe_cast_int16_int64(int64_t in)
0252 {
0253     if (check_cast_int16_int64(in))
0254         safe_math_fail("safe_math_fail safe_cast_int16_int64");
0255 
0256     return (int16_t)in;
0257 }
0258 
0259 static inline int16_t safe_cast_int16_uint64(uint64_t in)
0260 {
0261     if (in > INT16_MAX)
0262         safe_math_fail("safe_math_fail safe_cast_int16_uint64");
0263 
0264     return (int16_t)in;
0265 }
0266 
0267 static inline int32_t safe_cast_int32_uint32(uint32_t in)
0268 {
0269     if (check_cast_int32_uint32(in))
0270         safe_math_fail("safe_math_fail safe_cast_int32_uint32");
0271 
0272     return (int32_t)in;
0273 }
0274 
0275 static inline int32_t safe_cast_int32_int64(int64_t in)
0276 {
0277     if (check_cast_int32_int64(in))
0278         safe_math_fail("safe_math_fail safe_cast_int32_int64");
0279 
0280     return (int32_t)in;
0281 }
0282 
0283 static inline int32_t safe_cast_int32_uint64(uint64_t in)
0284 {
0285     if (check_cast_int32_uint64(in))
0286         safe_math_fail("safe_math_fail safe_cast_int32_uint64");
0287 
0288     return (int32_t)in;
0289 }
0290 
0291 static inline int64_t safe_cast_int64_uint64(uint64_t in)
0292 {
0293     if (check_cast_int64_uint64(in))
0294         safe_math_fail("safe_math_fail safe_cast_int64_uint64");
0295 
0296     return (int64_t)in;
0297 }
0298 
0299 static inline uint8_t safe_cast_uint8_int32(int32_t in)
0300 {
0301     if (check_cast_uint8_int32(in))
0302         safe_math_fail("safe_math_fail safe_cast_uint8_int32");
0303 
0304     return (uint8_t)in;
0305 }
0306 
0307 static inline uint8_t safe_cast_uint8_uint32(uint32_t in)
0308 {
0309     if (check_cast_uint8_uint32(in))
0310         safe_math_fail("safe_math_fail safe_cast_uint8_uint32");
0311 
0312     return (uint8_t)in;
0313 }
0314 
0315 static inline uint8_t safe_cast_uint8_int64(int64_t in)
0316 {
0317     if (check_cast_uint8_int64(in))
0318         safe_math_fail("safe_math_fail safe_cast_uint8_int64");
0319 
0320     return (uint8_t)in;
0321 }
0322 
0323 static inline uint8_t safe_cast_uint8_uint64(uint64_t in)
0324 {
0325     if (check_cast_uint8_uint64(in))
0326         safe_math_fail("safe_math_fail safe_cast_uint8_uint64");
0327 
0328     return (uint8_t)in;
0329 }
0330 
0331 static inline uint16_t safe_cast_uint16_int32(int32_t in)
0332 {
0333     if (check_cast_uint16_int32(in))
0334         safe_math_fail("safe_math_fail safe_cast_uint16_int32");
0335 
0336     return (uint16_t)in;
0337 }
0338 
0339 static inline uint16_t safe_cast_uint16_uint32(uint32_t in)
0340 {
0341     if (check_cast_uint16_uint32(in))
0342         safe_math_fail("safe_math_fail safe_cast_uint16_uint32");
0343 
0344     return (uint16_t)in;
0345 }
0346 
0347 static inline uint16_t safe_cast_uint16_int64(int64_t in)
0348 {
0349     if (check_cast_uint16_int64(in))
0350         safe_math_fail("safe_math_fail safe_cast_uint16_int64");
0351 
0352     return (uint16_t)in;
0353 }
0354 
0355 static inline uint16_t safe_cast_uint16_uint64(uint64_t in)
0356 {
0357     if (check_cast_uint16_uint64(in))
0358         safe_math_fail("safe_math_fail safe_cast_int16_uint64");
0359 
0360     return (uint16_t)in;
0361 }
0362 
0363 static inline uint32_t safe_cast_uint32_int32(int32_t in)
0364 {
0365     if (check_cast_uint32_int32(in))
0366         safe_math_fail("safe_math_fail safe_cast_uint32_int32");
0367 
0368     return (uint32_t)in;
0369 }
0370 
0371 static inline uint32_t safe_cast_uint32_int64(int64_t in)
0372 {
0373     if (check_cast_uint32_int64(in))
0374         safe_math_fail("safe_math_fail safe_cast_int32_int64");
0375 
0376     return (uint32_t)in;
0377 }
0378 
0379 static inline uint32_t safe_cast_uint32_uint64(uint64_t in)
0380 {
0381     if (check_cast_uint32_uint64(in))
0382         safe_math_fail("safe_math_fail safe_cast_uint32_uint64");
0383 
0384     return (uint32_t)in;
0385 }
0386 
0387 static inline uint64_t safe_cast_uint64_int64(int64_t in)
0388 {
0389     if (check_cast_uint64_int64(in))
0390         safe_math_fail("safe_math_fail safe_cast_int64_uint64");
0391 
0392     return (uint64_t)in;
0393 }
0394 
0395 // Addition
0396 /*
0397     For addition and multiplication, there will be checks for the following matrix:
0398     - int32
0399     - uint32
0400     - int64
0401     - uint64
0402 
0403     If you want to add smaller types, then do it inside the appropriate safe_cast function,
0404     or if adding one of the above and a smaller type, pass it into one that takes a larger
0405     size of the same type, for example, uint16 -> uint32.
0406 */
0407 
0408 static inline int32_t safe_add_int32_int32(int32_t a, int32_t b)
0409 {
0410     return safe_cast_int32_int64((int64_t)a + b);
0411 }
0412 
0413 static inline bool check_add_int32_int32(int32_t a, int32_t b, int32_t* ret)
0414 {
0415     int64_t tmp = (int64_t)a + b;
0416     *ret = (int32_t)tmp;
0417     return check_cast_int32_int64(tmp) == 0;
0418 }
0419 
0420 static inline int32_t safe_add_int32_uint32(int32_t a, uint32_t b)
0421 {
0422     return safe_cast_int32_int64((int64_t)a + b);
0423 }
0424 
0425 static inline bool check_add_int32_uint32(int32_t a, uint32_t b, int32_t* ret)
0426 {
0427     int64_t tmp = (int64_t)a + b;
0428     *ret = (int32_t)tmp;
0429     return check_cast_int32_int64(tmp) == 0;
0430 }
0431 
0432 static inline int32_t safe_add_int32_int64(int32_t a, int64_t b)
0433 {
0434     int64_t tmp = (int64_t)((uint64_t)a + (uint64_t)b);
0435     
0436     if (a >= 0)
0437     {
0438         // mixed sign cannot overflow
0439         if (b >= 0 && tmp < a)
0440             safe_math_fail("safe_math_fail safe_add_int32_int64");
0441     }
0442     else
0443     {
0444         // lhs negative
0445         if (b < 0 && tmp > a)
0446             safe_math_fail("safe_math_fail safe_add_int32_int64");
0447     }
0448 
0449     return safe_cast_int32_int64(tmp);
0450 }
0451 
0452 static inline bool check_add_int32_int64(int32_t a, int64_t b, int32_t* ret)
0453 {
0454     int64_t tmp = (int64_t)((uint64_t)a + (uint64_t)b);
0455     *ret = (int32_t)tmp;
0456 
0457     if (a >= 0)
0458     {
0459         // mixed sign cannot overflow
0460         if (b >= 0 && tmp < a)
0461             return false;
0462     }
0463     else
0464     {
0465         // lhs negative
0466         if (b < 0 && tmp > a)
0467             return false;
0468     }
0469 
0470     return check_cast_int32_int64(tmp) == 0;
0471 }
0472 
0473 static inline int32_t safe_add_int32_uint64(int32_t a, uint64_t b)
0474 {
0475     if ((uint32_t)(b >> 32) == 0)
0476     {
0477         // Now it just happens to work out that the standard behavior does what we want
0478         // Adding explicit casts to show exactly what's happening here
0479         uint32_t tmp = (uint32_t)a + (uint32_t)b;
0480 
0481         if ((int32_t)tmp >= a)
0482         {
0483             return (int32_t)tmp;
0484         }
0485     }
0486 
0487     safe_math_fail("safe_math_fail safe_add_int32_uint64");
0488 }
0489 
0490 static inline bool check_add_int32_uint64(int32_t a, uint64_t b, int32_t* ret)
0491 {
0492     if ((uint32_t)(b >> 32) == 0)
0493     {
0494         // Now it just happens to work out that the standard behavior does what we want
0495         // Adding explicit casts to show exactly what's happening here
0496         uint32_t tmp = (uint32_t)a + (uint32_t)b;
0497         *ret = (int32_t)tmp;
0498 
0499         if ((int32_t)tmp >= a)
0500         {
0501             return true;
0502         }
0503     }
0504 
0505     return false;
0506 }
0507 
0508 static inline uint32_t safe_add_uint32_int32(uint32_t a, int32_t b)
0509 {
0510     return safe_cast_uint32_int64((int64_t)a + b);
0511 }
0512 
0513 static inline bool check_add_uint32_int32(uint32_t a, int32_t b, uint32_t* ret)
0514 {
0515     int64_t tmp = (int64_t)a + b;
0516     *ret = (uint32_t)tmp;
0517     return check_cast_uint32_int64(tmp) == 0;
0518 }
0519 
0520 static inline uint32_t safe_add_uint32_uint32(uint32_t a, uint32_t b)
0521 {
0522     uint32_t tmp = a + b;
0523     
0524     if (tmp < a)
0525     {
0526         safe_math_fail("safe_math_fail safe_add_uint32_uint32");
0527     }
0528 
0529     return tmp;
0530 }
0531 
0532 static inline bool check_add_uint32_uint32(uint32_t a, uint32_t b, uint32_t* ret)
0533 {
0534     uint32_t tmp = a + b;
0535     *ret = tmp;
0536     return tmp >= a;
0537 }
0538 
0539 static inline uint32_t safe_add_uint32_int64(uint32_t a, int64_t b)
0540 {
0541     if (b < 0)
0542     {
0543         if (a >= safe_abs64(b)) //negation is safe, since rhs is 64-bit
0544         {
0545             return (uint32_t)(a + b);
0546         }
0547     }
0548     else
0549     {
0550         // now we know that rhs can be safely cast into an std::uint64_t
0551         uint64_t tmp = (uint64_t)a + (uint64_t)b;
0552 
0553         // special case - rhs cannot be larger than 0x7fffffffffffffff, lhs cannot be larger than 0xffffffff
0554         // it is not possible for the operation above to overflow, so just check max
0555         return safe_cast_uint32_uint64(tmp);
0556     }
0557 
0558     safe_math_fail("safe_math_fail safe_add_uint32_int64");
0559 }
0560 
0561 static inline bool check_add_uint32_int64(uint32_t a, int64_t b, uint32_t* ret)
0562 {
0563     if (b < 0)
0564     {
0565         if (a >= safe_abs64(b)) //negation is safe, since rhs is 64-bit
0566         {
0567             *ret = (uint32_t)(a + b);
0568             return true;
0569         }
0570     }
0571     else
0572     {
0573         // now we know that rhs can be safely cast into an std::uint64_t
0574         uint64_t tmp = (uint64_t)a + (uint64_t)b;
0575 
0576         // special case - rhs cannot be larger than 0x7fffffffffffffff, lhs cannot be larger than 0xffffffff
0577         // it is not possible for the operation above to overflow, so just check max
0578         *ret = (uint32_t)tmp;
0579         return check_cast_uint32_uint64(tmp) == 0;
0580     }
0581 
0582     return false;
0583 }
0584 
0585 static inline uint32_t safe_add_uint32_uint64(uint32_t a, uint64_t b)
0586 {
0587     uint64_t tmp = (uint64_t)a + b;
0588     
0589     if (tmp >= a && tmp <= UINT32_MAX)
0590     {
0591         return (uint32_t)tmp;
0592     }
0593 
0594     safe_math_fail("safe_math_fail safe_add_uint32_uint64");
0595 }
0596 
0597 static inline bool check_add_uint32_uint64(uint32_t a, uint64_t b, uint32_t* ret)
0598 {
0599     uint64_t tmp = (uint64_t)a + b;
0600     *ret = (uint32_t)tmp;
0601 
0602     return (tmp >= a && tmp <= UINT32_MAX);
0603 }
0604 
0605 static inline int64_t safe_add_int64_int32(int64_t a, int32_t b)
0606 {
0607     int64_t tmp = (int64_t)((uint64_t)a + (uint64_t)b);
0608 
0609     if (a >= 0)
0610     {
0611         // mixed sign cannot overflow
0612         if (b >= 0 && tmp < a)
0613             safe_math_fail("safe_math_fail safe_add_int64_int32");
0614     }
0615     else
0616     {
0617         // lhs negative
0618         if (b < 0 && tmp > a)
0619             safe_math_fail("safe_math_fail safe_add_int64_int32");
0620     }
0621 
0622     return tmp;
0623 }
0624 
0625 static inline bool check_add_int64_int32(int64_t a, int32_t b, int64_t* ret)
0626 {
0627     int64_t tmp = (int64_t)((uint64_t)a + (uint64_t)b);
0628     *ret = tmp;
0629 
0630     if (a >= 0)
0631     {
0632         // mixed sign cannot overflow
0633         if (b >= 0 && tmp < a)
0634             return false;
0635     }
0636     else
0637     {
0638         // lhs negative
0639         if (b < 0 && tmp > a)
0640             return false;
0641     }
0642 
0643     return true;
0644 }
0645 
0646 static inline int64_t safe_add_int64_uint32(int64_t a, uint32_t b)
0647 {
0648     uint64_t tmp = (uint64_t)a + (uint64_t)b;
0649 
0650     if ((int64_t)tmp >= a)
0651     {
0652         return (int64_t)tmp;
0653     }
0654 
0655     safe_math_fail("safe_math_fail safe_add_int64_uint32");
0656 }
0657 
0658 static inline bool check_add_int64_uint32(int64_t a, uint32_t b, int64_t* ret)
0659 {
0660     uint64_t tmp = (uint64_t)a + (uint64_t)b;
0661     *ret = (int64_t)tmp;
0662 
0663     return ((int64_t)tmp >= a);
0664 }
0665 
0666 static inline int64_t safe_add_int64_int64(int64_t a, int64_t b)
0667 {
0668     int64_t tmp = (int64_t)((uint64_t)a + (uint64_t)b);
0669 
0670     if (a >= 0)
0671     {
0672         // mixed sign cannot overflow
0673         if (b >= 0 && tmp < a)
0674             safe_math_fail("safe_math_fail safe_add_int64_int64");
0675     }
0676     else
0677     {
0678         // lhs negative
0679         if (b < 0 && tmp > a)
0680             safe_math_fail("safe_math_fail safe_add_int64_int64");
0681     }
0682 
0683     return tmp;
0684 }
0685 
0686 static inline bool check_add_int64_int64(int64_t a, int64_t b, int64_t* ret)
0687 {
0688     int64_t tmp = (int64_t)((uint64_t)a + (uint64_t)b);
0689     *ret = tmp;
0690 
0691     if (a >= 0)
0692     {
0693         // mixed sign cannot overflow
0694         if (b >= 0 && tmp < a)
0695             return false;
0696     }
0697     else
0698     {
0699         // lhs negative
0700         if (b < 0 && tmp > a)
0701             return false;
0702     }
0703 
0704     return true;
0705 }
0706 
0707 static inline int64_t safe_add_int64_uint64(int64_t a, uint64_t b)
0708 {
0709     uint64_t tmp = (uint64_t)a + b;
0710 
0711     if ((int64_t)tmp >= a)
0712     {
0713         return (int64_t)tmp;
0714     }
0715 
0716     safe_math_fail("safe_math_fail safe_add_int64_uint64");
0717 }
0718 
0719 static inline bool check_add_int64_uint64(int64_t a, uint64_t b, int64_t* ret)
0720 {
0721     uint64_t tmp = (uint64_t)a + b;
0722     *ret = (int64_t)tmp;
0723 
0724     return ((int64_t)tmp >= a);
0725 }
0726 
0727 static inline uint64_t safe_add_uint64_int32(uint64_t a, int32_t b)
0728 {
0729     uint64_t tmp = 0;
0730 
0731     if (b < 0)
0732     {
0733         // So we're effectively subtracting
0734         tmp = safe_abs32(b);
0735 
0736         if (tmp <= a)
0737         {
0738             return a - tmp;
0739         }
0740     }
0741     else
0742     {
0743         // now we know that rhs can be safely cast into an std::uint64_t
0744         tmp = (uint64_t)a + (uint64_t)b;
0745 
0746         // We added and it did not become smaller
0747         if (tmp >= a)
0748         {
0749             return tmp;
0750         }
0751     }
0752 
0753     safe_math_fail("safe_math_fail safe_add_uint64_int32");
0754 }
0755 
0756 static inline bool check_add_uint64_int32(uint64_t a, int32_t b, uint64_t* ret)
0757 {
0758     uint64_t tmp = 0;
0759 
0760     if (b < 0)
0761     {
0762         // So we're effectively subtracting
0763         tmp = safe_abs32(b);
0764 
0765         if (tmp <= a)
0766         {
0767             *ret = a - tmp;
0768             return true;
0769         }
0770     }
0771     else
0772     {
0773         // now we know that rhs can be safely cast into an std::uint64_t
0774         tmp = (uint64_t)a + (uint64_t)b;
0775 
0776         // We added and it did not become smaller
0777         if (tmp >= a)
0778         {
0779             *ret = tmp;
0780             return true;
0781         }
0782     }
0783 
0784     return false;
0785 }
0786 
0787 
0788 static inline uint64_t safe_add_uint64_uint32(uint64_t a, uint32_t b)
0789 {
0790     uint64_t tmp = (uint64_t)a + (uint64_t)b;
0791 
0792     // We added and it didn't get smaller
0793     if (tmp >= a)
0794     {
0795         return tmp;
0796     }
0797 
0798     safe_math_fail("safe_math_fail safe_add_uint64_uint32");
0799 }
0800 
0801 static inline bool check_add_uint64_uint32(uint64_t a, uint32_t b, uint64_t* ret)
0802 {
0803     uint64_t tmp = (uint64_t)a + (uint64_t)b;
0804     *ret = tmp;
0805 
0806     // We added and it didn't get smaller
0807     return (tmp >= a);
0808 }
0809 
0810 static inline uint64_t safe_add_uint64_int64(uint64_t a, int64_t b)
0811 {
0812     uint64_t tmp = 0;
0813 
0814     if (b < 0)
0815     {
0816         // So we're effectively subtracting
0817         tmp = safe_abs64(b);
0818 
0819         if (tmp <= a)
0820         {
0821             return a - tmp;
0822         }
0823     }
0824     else
0825     {
0826         // now we know that rhs can be safely cast into an std::uint64_t
0827         tmp = (uint64_t)a + (uint64_t)b;
0828 
0829         // We added and it did not become smaller
0830         if (tmp >= a)
0831         {
0832             return tmp;
0833         }
0834     }
0835 
0836     safe_math_fail("safe_math_fail safe_add_uint64_int64");
0837 }
0838 
0839 static inline bool check_add_uint64_int64(uint64_t a, int64_t b, uint64_t* ret)
0840 {
0841     uint64_t tmp = 0;
0842 
0843     if (b < 0)
0844     {
0845         // So we're effectively subtracting
0846         tmp = safe_abs64(b);
0847 
0848         if (tmp <= a)
0849         {
0850             *ret = a - tmp;
0851             return true;
0852         }
0853     }
0854     else
0855     {
0856         // now we know that rhs can be safely cast into an std::uint64_t
0857         tmp = (uint64_t)a + (uint64_t)b;
0858 
0859         // We added and it did not become smaller
0860         if (tmp >= a)
0861         {
0862             *ret = tmp;
0863             return true;
0864         }
0865     }
0866 
0867     return false;
0868 }
0869 
0870 static inline uint64_t safe_add_uint64_uint64(uint64_t a, uint64_t b)
0871 {
0872     uint64_t tmp = a + b;
0873 
0874     if(tmp < a)
0875         safe_math_fail("safe_math_fail safe_add_uint64_uint64");
0876 
0877     return tmp;
0878 }
0879 
0880 static inline bool check_add_uint64_uint64(uint64_t a, uint64_t b, uint64_t* ret)
0881 {
0882     uint64_t tmp = a + b;
0883     *ret = tmp;
0884     return (tmp >= a);
0885 }
0886 
0887 // As we're working in C, use defines
0888 // It would be nice to use an enum, but the compiler 
0889 // will complain that it isn't a proper C++ enum
0890 #define SAFE_INT_MUL_FAIL 0
0891 #define SAFE_INT_MUL_SUCCESS 1
0892 
0893 // Multiplication primatives
0894 #if SAFEINT_MULTIPLY_METHOD == SAFEINT_MULTIPLY_INT128
0895 
0896 static inline int MultiplyUint64(uint64_t a, uint64_t b, uint64_t* pRet)
0897 {
0898     unsigned __int128 tmp = (unsigned __int128)a * (unsigned __int128)b;
0899 
0900     if ((tmp >> 64) == 0)
0901     {
0902         *pRet = (uint64_t)tmp;
0903         return SAFE_INT_MUL_SUCCESS;
0904     }
0905 
0906     return SAFE_INT_MUL_FAIL;
0907 }
0908 
0909 static inline int MultiplyInt64(int64_t a, int64_t b, int64_t* pRet)
0910 {
0911     __int128 tmp = (__int128)a * (__int128)b;
0912     int64_t tmp_high = (int64_t)((unsigned __int128)tmp >> 64);
0913     *pRet = (int64_t)tmp;
0914 
0915     // If only one input is negative, result must be negative, or zero
0916     if ((a ^ b) < 0)
0917     {
0918         if ((tmp_high == -1 && *pRet < 0) ||
0919             (tmp_high == 0 && *pRet == 0))
0920         {
0921             return SAFE_INT_MUL_SUCCESS;
0922         }
0923     }
0924     else
0925     {
0926         if (tmp_high == 0 && (uint64_t)*pRet <= (uint64_t)INT64_MAX)
0927         {
0928             return SAFE_INT_MUL_SUCCESS;
0929         }
0930     }
0931 
0932     return SAFE_INT_MUL_FAIL;
0933 }
0934 
0935 #elif SAFEINT_MULTIPLY_METHOD == SAFEINT_MULTIPLY_INTRINSICS // Implies Visual Studio compiler
0936 
0937 // As usual, unsigned is easy
0938 static inline int MultiplyUint64(uint64_t a, uint64_t b, uint64_t * pRet)
0939 {
0940     uint64_t ulHigh = 0;
0941     *pRet = _umul128(a, b, &ulHigh);
0942     return ulHigh == 0 ? SAFE_INT_MUL_SUCCESS : SAFE_INT_MUL_FAIL;
0943 }
0944 
0945 // Signed, is not so easy
0946 static inline int MultiplyInt64(int64_t a, int64_t b, int64_t* pRet)
0947 {
0948     int64_t llHigh = 0;
0949     *pRet = _mul128(a, b, &llHigh);
0950 
0951     // Now we need to figure out what we expect
0952     // If llHigh is 0, then treat *pRet as unsigned
0953     // If llHigh is < 0, then treat *pRet as signed
0954 
0955     if ((a ^ b) < 0)
0956     {
0957         // Negative (or zero) result expected
0958         if (llHigh == -1 && *pRet < 0 ||
0959             llHigh == 0 && *pRet == 0)
0960         {
0961             // Everything is within range
0962             return SAFE_INT_MUL_SUCCESS;
0963         }
0964     }
0965     else
0966     {
0967         // Result should be positive
0968         // Check for overflow
0969         if (llHigh == 0 && (uint64_t)*pRet <= (uint64_t)INT64_MAX)
0970             return SAFE_INT_MUL_SUCCESS;
0971     }
0972     return SAFE_INT_MUL_FAIL;
0973 }
0974 #elif SAFEINT_MULTIPLY_METHOD == SAFEINT_MULTIPLY_BUILTIN // Implies gcc or clang
0975 
0976 static inline int MultiplyUint64(uint64_t a, uint64_t b, uint64_t* pRet)
0977 {
0978     return !__builtin_umulll_overflow(a, b, (unsigned long long*)pRet) ? SAFE_INT_MUL_SUCCESS : SAFE_INT_MUL_FAIL;
0979 }
0980 
0981 static inline int MultiplyInt64(int64_t a, int64_t b, int64_t* pRet)
0982 {
0983     return !__builtin_smulll_overflow(a, b, (long long*)pRet) ? SAFE_INT_MUL_SUCCESS : SAFE_INT_MUL_FAIL;
0984 }
0985 
0986 #elif SAFEINT_MULTIPLY_METHOD == SAFEINT_MULTIPLY_MATH // Just going to have to do the math...
0987 
0988 static inline int MultiplyUint64(uint64_t a, uint64_t b, uint64_t* pRet)
0989 {
0990     uint32_t a_high = a >> 32;
0991     uint32_t a_low = (uint32_t)a;
0992     uint32_t b_high = b >> 32;
0993     uint32_t b_low = (uint32_t)b;
0994     uint64_t tmp = 0;
0995     uint64_t tmp2 = 0;
0996 
0997     /*
0998     * Now we have the equivalent of (a_high * 2^32 + a_low) * (b_high * 2^32 + b_low)
0999     * Expanding:
1000     * result = a_high * b_high * 2^64 + a_high * b_low * 2^32 + b_high * a_low * 2^32 + a_low * b_low
1001     * We now get to short circult some things - if a_high > 0 && b_high > 0, fail
1002     * and this then implies that only one of the two middle expressions must be evaluated and checked if the result is >= 2^32
1003     * finally, do the last term, check addition
1004     */
1005 
1006     if (a_high > 0 && b_high > 0)
1007     {
1008         return SAFE_INT_MUL_FAIL;
1009     }
1010 
1011     if (a_high > 0)
1012     {
1013         tmp = (uint64_t)a_high * b_low;
1014     }
1015     else
1016     {
1017         tmp = (uint64_t)b_high * a_low;
1018     }
1019 
1020     if (tmp >> 32 != 0)
1021     {
1022         return SAFE_INT_MUL_FAIL;
1023     }
1024 
1025     tmp2 = (uint64_t)a_low * b_low;
1026     *pRet = (tmp << 32) + tmp2;
1027     return *pRet >= tmp2 ? SAFE_INT_MUL_SUCCESS : SAFE_INT_MUL_FAIL;
1028 }
1029 
1030 static inline int MultiplyInt64(int64_t a, int64_t b, int64_t* pRet)
1031 {
1032     bool aNegative = false;
1033     bool bNegative = false;
1034 
1035     uint64_t tmp = 0;
1036     int64_t a1 = a;
1037     int64_t b1 = b;
1038 
1039     if (a1 < 0)
1040     {
1041         aNegative = true;
1042         a1 = (int64_t)safe_abs64(a1);
1043     }
1044 
1045     if (b1 < 0)
1046     {
1047         bNegative = true;
1048         b1 = (int64_t)safe_abs64(b);
1049     }
1050 
1051     if (MultiplyUint64((uint64_t)a1, (uint64_t)b1, &tmp))
1052     {
1053         // The unsigned multiplication didn't overflow
1054         if (aNegative ^ bNegative)
1055         {
1056             // Result must be negative
1057             if (tmp <= (uint64_t)INT64_MIN)
1058             {
1059                 *pRet = (int64_t)negate64((int64_t)tmp);
1060                 return SAFE_INT_MUL_SUCCESS;
1061             }
1062         }
1063         else
1064         {
1065             // Result must be positive
1066             if (tmp <= (uint64_t)INT64_MAX)
1067             {
1068                 *pRet = (int64_t)tmp;
1069                 return SAFE_INT_MUL_SUCCESS;
1070             }
1071         }
1072     }
1073 
1074     return SAFE_INT_MUL_FAIL;
1075 }
1076 
1077 #else // Shouldn't happen, go find out what's broken
1078 // If you are aware of intrinsics for some other platform, please file an issue
1079 # error Intrinsics enabled, no available intrinics defined
1080 #endif
1081 
1082 static inline int32_t safe_mul_int32_int32(int32_t a, int32_t b)
1083 {
1084     int64_t tmp = (int64_t)a * (int64_t)b;
1085     return safe_cast_int32_int64(tmp);
1086 }
1087 
1088 static inline bool check_mul_int32_int32(int32_t a, int32_t b, int32_t* ret)
1089 {
1090     int64_t tmp = (int64_t)a * (int64_t)b;
1091     *ret = (int32_t)tmp;
1092     return check_cast_int32_int64(tmp) == 0;
1093 }
1094 
1095 static inline int32_t safe_mul_int32_uint32(int32_t a, uint32_t b)
1096 {
1097     int64_t tmp = (int64_t)a * (int64_t)b;
1098     return safe_cast_int32_int64(tmp);
1099 }
1100 
1101 static inline bool check_mul_int32_uint32(int32_t a, uint32_t b, int32_t* ret)
1102 {
1103     int64_t tmp = (int64_t)a * (int64_t)b;
1104     *ret = (int32_t)tmp;
1105     return check_cast_int32_int64(tmp) == 0;
1106 }
1107 
1108 static inline int32_t safe_mul_int32_int64(int32_t a, int64_t b)
1109 {
1110     int64_t tmp = 0;
1111 
1112     if (MultiplyInt64((int64_t)a, b, &tmp))
1113     {
1114         return safe_cast_int32_int64(tmp);
1115     }
1116 
1117     safe_math_fail("safe_math_fail safe_mul_int32_int64");
1118 }
1119 
1120 static inline bool check_mul_int32_int64(int32_t a, int64_t b, int32_t* ret)
1121 {
1122     int64_t tmp = 0;
1123 
1124     if (MultiplyInt64((int64_t)a, b, &tmp))
1125     {
1126         *ret = (int32_t)tmp;
1127         return check_cast_int32_int64(tmp) == 0;
1128     }
1129 
1130     return false;
1131 }
1132 
1133 static inline int32_t safe_mul_int32_uint64(int32_t a, uint64_t b)
1134 {
1135     uint64_t tmp = 0;
1136     if (a < 0)
1137     {
1138         // Flip sign, use the unsigned function
1139         uint64_t a2 = safe_abs64(a);
1140         if (MultiplyUint64(a2, b, &tmp) == SAFE_INT_MUL_SUCCESS && tmp <= (uint64_t)INT32_MAX + 1)
1141         {
1142             // Not too big, flip it back
1143             return (int32_t)(tmp + 1);
1144         }
1145     }
1146     else
1147     {
1148         if (MultiplyUint64((uint64_t)a, b, &tmp) == SAFE_INT_MUL_SUCCESS && tmp <= INT32_MAX)
1149         {
1150             return (int32_t)tmp;
1151         }
1152     }
1153  
1154     safe_math_fail("safe_math_fail safe_mul_int32_uint64");
1155 }
1156 
1157 static inline bool check_mul_int32_uint64(int32_t a, uint64_t b, int32_t* ret)
1158 {
1159     uint64_t tmp = 0;
1160     if (a < 0)
1161     {
1162         // Flip sign, use the unsigned function
1163         uint64_t a2 = safe_abs64(a);
1164         if (MultiplyUint64(a2, b, &tmp) == SAFE_INT_MUL_SUCCESS && tmp <= (uint64_t)INT32_MAX + 1)
1165         {
1166             // Not too big, flip it back
1167             *ret = (int32_t)(tmp + 1);
1168             return true;
1169         }
1170     }
1171     else
1172     {
1173         if (MultiplyUint64((uint64_t)a, b, &tmp) == SAFE_INT_MUL_SUCCESS && tmp <= INT32_MAX)
1174         {
1175             *ret = (int32_t)tmp;
1176             return true;
1177         }
1178     }
1179 
1180     return false;
1181 }
1182 
1183 static inline uint32_t safe_mul_uint32_int32(uint32_t a, int32_t b)
1184 {
1185     int64_t tmp = (int64_t)a * (int64_t)b;
1186     return safe_cast_uint32_int64(tmp);
1187 }
1188 
1189 static inline bool check_mul_uint32_int32(uint32_t a, int32_t b, uint32_t* ret)
1190 {
1191     int64_t tmp = (int64_t)a * (int64_t)b;
1192     *ret = (uint32_t)tmp;
1193     return check_cast_uint32_int64(tmp) == 0;
1194 }
1195 
1196 static inline uint32_t safe_mul_uint32_uint32(uint32_t a, uint32_t b)
1197 {
1198     uint64_t tmp = (uint64_t)a * (uint64_t)b;
1199     return safe_cast_uint32_uint64(tmp);
1200 }
1201 
1202 static inline bool check_mul_uint32_uint32(uint32_t a, uint32_t b, uint32_t* ret)
1203 {
1204     uint64_t tmp = (uint64_t)a * (uint64_t)b;
1205     *ret = (uint32_t)tmp;
1206     return check_cast_uint32_uint64(tmp) == 0;
1207 }
1208 
1209 static inline uint32_t safe_mul_uint32_int64(uint32_t a, int64_t b)
1210 {
1211     int64_t tmp = 0;
1212 
1213     if (MultiplyInt64((int64_t)a, b, &tmp) == SAFE_INT_MUL_SUCCESS && tmp <= UINT32_MAX && tmp >= 0)
1214     {
1215         return (uint32_t)tmp;
1216     }
1217 
1218     safe_math_fail("safe_math_fail safe_mul_uint32_int64");
1219 }
1220 
1221 static inline bool check_mul_uint32_int64(uint32_t a, int64_t b, uint32_t* ret)
1222 {
1223     int64_t tmp = 0;
1224 
1225     if (MultiplyInt64((int64_t)a, b, &tmp) == SAFE_INT_MUL_SUCCESS && tmp <= UINT32_MAX && tmp >= 0)
1226     {
1227         *ret = (uint32_t)tmp;
1228         return true;
1229     }
1230 
1231     return false;
1232 }
1233 
1234 static inline uint32_t safe_mul_uint32_uint64(uint32_t a, uint64_t b)
1235 {
1236     uint64_t tmp = 0;
1237 
1238     if (MultiplyUint64((uint64_t)a, b, &tmp) == SAFE_INT_MUL_SUCCESS && tmp <= UINT32_MAX)
1239     {
1240         return (uint32_t)tmp;
1241     }
1242 
1243     safe_math_fail("safe_math_fail safe_mul_uint32_uint64");
1244 }
1245 
1246 static inline bool check_mul_uint32_uint64(uint32_t a, uint64_t b, uint32_t* ret)
1247 {
1248     uint64_t tmp = 0;
1249 
1250     if (MultiplyUint64((uint64_t)a, b, &tmp) == SAFE_INT_MUL_SUCCESS && tmp <= UINT32_MAX)
1251     {
1252         *ret = (uint32_t)tmp;
1253         return true;
1254     }
1255 
1256     return false;
1257 }
1258 
1259 static inline int64_t safe_mul_int64_int32(int64_t a, int32_t b)
1260 {
1261     int64_t tmp = 0;
1262 
1263     if (MultiplyInt64(a, (int64_t)b, &tmp) == SAFE_INT_MUL_SUCCESS)
1264     {
1265         return tmp;
1266     }
1267 
1268     safe_math_fail("safe_math_fail safe_mul_int64_int32");
1269 }
1270 
1271 static inline bool check_mul_int64_int32(int64_t a, int32_t b, int64_t* ret)
1272 {
1273     int64_t tmp = 0;
1274 
1275     if (MultiplyInt64(a, (int64_t)b, &tmp) == SAFE_INT_MUL_SUCCESS)
1276     {
1277         *ret = tmp;
1278         return true;
1279     }
1280 
1281     return false;
1282 }
1283 
1284 static inline int64_t safe_mul_int64_uint32(int64_t a, uint32_t b)
1285 {
1286     int64_t tmp = 0;
1287 
1288     if (MultiplyInt64(a, (int64_t)b, &tmp) == SAFE_INT_MUL_SUCCESS)
1289     {
1290         return tmp;
1291     }
1292 
1293     safe_math_fail("safe_math_fail safe_mul_int64_uint32");
1294 }
1295 
1296 static inline bool check_mul_int64_uint32(int64_t a, uint32_t b, int64_t* ret)
1297 {
1298     int64_t tmp = 0;
1299 
1300     if (MultiplyInt64(a, (int64_t)b, &tmp) == SAFE_INT_MUL_SUCCESS)
1301     {
1302         *ret = tmp;
1303         return true;
1304     }
1305 
1306     return false;
1307 }
1308 
1309 static inline int64_t safe_mul_int64_int64(int64_t a, int64_t b)
1310 {
1311     int64_t tmp = 0;
1312 
1313     if (MultiplyInt64(a, b, &tmp) == SAFE_INT_MUL_SUCCESS)
1314     {
1315         return tmp;
1316     }
1317 
1318     safe_math_fail("safe_math_fail safe_mul_int64_int64");
1319 }
1320 
1321 static inline bool check_mul_int64_int64(int64_t a, int64_t b, int64_t* ret)
1322 {
1323     int64_t tmp = 0;
1324 
1325     if (MultiplyInt64(a, b, &tmp) == SAFE_INT_MUL_SUCCESS)
1326     {
1327         *ret = tmp;
1328         return true;
1329     }
1330 
1331     return false;
1332 }
1333 
1334 static inline int64_t safe_mul_int64_uint64(int64_t a, uint64_t b)
1335 {
1336     uint64_t tmp = 0;
1337 
1338     if (a < 0)
1339     {
1340         uint64_t a2 = safe_abs64(a);
1341 
1342         if (MultiplyUint64(a2, b, &tmp) == SAFE_INT_MUL_SUCCESS && tmp <= (uint64_t)0x8000000000000000)
1343         {
1344             return negate64((int64_t)tmp);
1345         }
1346     }
1347     else
1348     {
1349         if (MultiplyUint64((uint64_t)a, b, &tmp) == SAFE_INT_MUL_SUCCESS && tmp <= (uint64_t)INT64_MAX)
1350         {
1351             return (int64_t)tmp;
1352         }
1353     }
1354 
1355     safe_math_fail("safe_math_fail safe_mul_int64_uint64");
1356 }
1357 
1358 static inline bool check_mul_int64_uint64(int64_t a, uint64_t b, int64_t* ret)
1359 {
1360     uint64_t tmp = 0;
1361 
1362     if (a < 0)
1363     {
1364         uint64_t a2 = safe_abs64(a);
1365 
1366         if (MultiplyUint64(a2, b, &tmp) == SAFE_INT_MUL_SUCCESS && tmp <= (uint64_t)0x8000000000000000)
1367         {
1368             *ret = negate64((int64_t)tmp);
1369             return true;
1370         }
1371     }
1372     else
1373     {
1374         if (MultiplyUint64((uint64_t)a, b, &tmp) == SAFE_INT_MUL_SUCCESS && tmp <= (uint64_t)INT64_MAX)
1375         {
1376             *ret = (int64_t)tmp;
1377             return true;
1378         }
1379     }
1380 
1381     return false;
1382 }
1383 
1384 static inline uint64_t safe_mul_uint64_int32(uint64_t a, int32_t b)
1385 {
1386     uint64_t tmp;
1387 
1388     if (b < 0)
1389     {
1390         if (a == 0)
1391             return 0;
1392 
1393         safe_math_fail("safe_math_fail safe_mul_uint64_int32");
1394     }
1395    
1396     if (MultiplyUint64(a, (uint64_t)b, &tmp) == SAFE_INT_MUL_SUCCESS)
1397     {
1398         return tmp;
1399     }
1400 
1401     safe_math_fail("safe_math_fail safe_mul_uint64_int32");
1402 }
1403 
1404 static inline bool check_mul_uint64_int32(uint64_t a, int32_t b, uint64_t* ret)
1405 {
1406     uint64_t tmp;
1407 
1408     if (b < 0)
1409     {
1410         if (a == 0)
1411         {
1412             *ret = 0;
1413             return true;
1414         }
1415 
1416         return false;
1417     }
1418 
1419     if (MultiplyUint64(a, (uint64_t)b, &tmp) == SAFE_INT_MUL_SUCCESS)
1420     {
1421         *ret = tmp;
1422         return true;
1423     }
1424 
1425     return false;
1426 }
1427 
1428 static inline uint64_t safe_mul_uint64_uint32(uint64_t a, uint32_t b)
1429 {
1430     uint64_t tmp;
1431 
1432     if (MultiplyUint64(a, (uint64_t)b, &tmp) == SAFE_INT_MUL_SUCCESS)
1433     {
1434         return tmp;
1435     }
1436 
1437     safe_math_fail("safe_math_fail safe_mul_uint64_uint32");
1438 }
1439 
1440 static inline bool check_mul_uint64_uint32(uint64_t a, uint32_t b, uint64_t* ret)
1441 {
1442     uint64_t tmp;
1443 
1444     if (MultiplyUint64(a, (uint64_t)b, &tmp) == SAFE_INT_MUL_SUCCESS)
1445     {
1446         *ret = tmp;
1447         return true;
1448     }
1449 
1450     return false;
1451 }
1452 
1453 static inline uint64_t safe_mul_uint64_int64(uint64_t a, int64_t b)
1454 {
1455     uint64_t tmp;
1456 
1457     if (b < 0)
1458     {
1459         if (a == 0)
1460             return 0;
1461 
1462         safe_math_fail("safe_math_fail safe_mul_uint64_int32");
1463     }
1464 
1465     if (MultiplyUint64(a, (uint64_t)b, &tmp) == SAFE_INT_MUL_SUCCESS)
1466     {
1467         return tmp;
1468     }
1469 
1470     safe_math_fail("safe_math_fail safe_mul_uint64_int64");
1471 }
1472 
1473 static inline bool check_mul_uint64_int64(uint64_t a, int64_t b, uint64_t* ret)
1474 {
1475     uint64_t tmp;
1476 
1477     if (b < 0)
1478     {
1479         if (a == 0)
1480         {
1481             *ret = 0;
1482             return true;
1483         }
1484 
1485         return false;
1486     }
1487 
1488     if (MultiplyUint64(a, (uint64_t)b, &tmp) == SAFE_INT_MUL_SUCCESS)
1489     {
1490         *ret = tmp;
1491         return true;
1492     }
1493 
1494     return false;
1495 }
1496 
1497 static inline uint64_t safe_mul_uint64_uint64(uint64_t a, uint64_t b)
1498 {
1499     uint64_t tmp;
1500 
1501     if (MultiplyUint64(a, b, &tmp) == SAFE_INT_MUL_SUCCESS)
1502     {
1503         return tmp;
1504     }
1505 
1506     safe_math_fail("safe_math_fail safe_mul_uint64_uint64");
1507 }
1508 
1509 static inline bool check_mul_uint64_uint64(uint64_t a, uint64_t b, uint64_t* ret)
1510 {
1511     return (MultiplyUint64(a, b, ret) == SAFE_INT_MUL_SUCCESS);
1512 }
1513 
1514 static inline int32_t safe_div_int32_int32(int32_t a, int32_t b)
1515 {
1516     if (b != 0 && !(a == INT32_MIN && b == -1))
1517     {
1518         return a / b;
1519     }
1520     safe_math_fail("safe_math_fail safe_div_int32_int32");
1521 }
1522 
1523 static inline bool check_div_int32_int32(int32_t a, int32_t b, int32_t* ret)
1524 {
1525     if (b != 0 && !(a == INT32_MIN && b == -1))
1526     {
1527         *ret = a / b;
1528         return true;
1529     }
1530     return false;
1531 }
1532 
1533 static inline int32_t safe_div_int32_uint32(int32_t a, uint32_t b)
1534 {
1535     if (b != 0)
1536     {
1537         return (int32_t)((int64_t)a / (int64_t)b);
1538     }
1539     safe_math_fail("safe_math_fail safe_div_int32_uint32");
1540 }
1541 
1542 static inline bool check_div_int32_uint32(int32_t a, uint32_t b, int32_t* ret)
1543 {
1544     if (b != 0)
1545     {
1546         *ret = (int32_t)((int64_t)a / (int64_t)b);
1547         return true;
1548     }
1549 
1550     return false;
1551 }
1552 
1553 static inline int32_t safe_div_int32_int64(int32_t a, int64_t b)
1554 {
1555     if (b != 0 && !(a == INT32_MIN && b == -1))
1556     {
1557         return (int32_t)(a / b);
1558     }
1559     safe_math_fail("safe_math_fail safe_div_int32_int64");
1560 }
1561 
1562 static inline bool check_div_int32_int64(int32_t a, int64_t b, int32_t* ret)
1563 {
1564     if (b != 0 && !(a == INT32_MIN && b == -1))
1565     {
1566         *ret = (int32_t)(a / b);
1567         return true;
1568     }
1569 
1570     return false;
1571 }
1572 
1573 static inline int32_t safe_div_int32_uint64(int32_t a, uint64_t b)
1574 {
1575     if (b == 0)
1576     {
1577         safe_math_fail("safe_math_fail safe_div_int32_uint64");
1578     }
1579 
1580     if (a > 0)
1581     {
1582         return (int32_t)((uint64_t)a / b);
1583     }
1584     else
1585     {
1586         uint64_t a2 = (uint64_t)safe_abs32(a);
1587         a2 /= b;
1588         return (int32_t)negate32((int32_t)a2);
1589     }
1590 }
1591 
1592 static inline bool check_div_int32_uint64(int32_t a, uint64_t b, int32_t* ret)
1593 {
1594     if (b == 0)
1595     {
1596         return false;
1597     }
1598 
1599     if (a > 0)
1600     {
1601         *ret = (int32_t)((uint64_t)a / b);
1602         return true;
1603     }
1604     else
1605     {
1606         uint64_t a2 = (uint64_t)safe_abs32(a);
1607         a2 /= b;
1608         *ret = (int32_t)negate32((int32_t)a2);
1609         return true;
1610     }
1611 }
1612 
1613 static inline uint32_t safe_div_uint32_int32(uint32_t a, int32_t b)
1614 {
1615     // Follow original SafeInt logic for this case
1616     if (b == 0) // div 0 always a problem
1617     {
1618         safe_math_fail("safe_math_fail safe_div_uint32_int32");
1619     }
1620 
1621     if (a == 0) // zero divided by anything is zero
1622     {
1623         return 0;
1624     }
1625 
1626     if (b > 0) // if b is positive, just do the math
1627     {
1628         return (a / (uint32_t)b);
1629     }
1630     else // now have to check magnitude
1631     {
1632         uint32_t tmp = safe_abs32(b);
1633 
1634         if (a < tmp)
1635         {
1636             return 0;
1637         }
1638     }
1639 
1640     safe_math_fail("safe_math_fail safe_div_uint32_int32");
1641 }
1642 
1643 static inline bool check_div_uint32_int32(uint32_t a, int32_t b, uint32_t* ret)
1644 {
1645     // Follow original SafeInt logic for this case
1646     if (b == 0) // div 0 always a problem
1647     {
1648         return false;
1649     }
1650 
1651     if (a == 0) // zero divided by anything is zero
1652     {
1653         *ret = 0;
1654         return true;
1655     }
1656 
1657     if (b > 0) // if b is positive, just do the math
1658     {
1659         *ret = (a / (uint32_t)b);
1660         return true;
1661     }
1662     else // now have to check magnitude
1663     {
1664         uint32_t tmp = safe_abs32(b);
1665 
1666         if (a < tmp)
1667         {
1668             *ret = 0;
1669             return true;
1670         }
1671     }
1672 
1673     return false;
1674 }
1675 
1676 static inline uint32_t safe_div_uint32_uint32(uint32_t a, uint32_t b)
1677 {
1678     if (b > 0)
1679     {
1680         return (uint32_t)(a / b);
1681     }
1682     safe_math_fail("safe_math_fail safe_div_uint32_uint32");
1683 }
1684 
1685 static inline bool check_div_uint32_uint32(uint32_t a, uint32_t b, uint32_t* ret)
1686 {
1687     if (b > 0)
1688     {
1689         *ret = (uint32_t)(a / b);
1690         return true;
1691     }
1692 
1693     return false;
1694 }
1695 
1696 static inline uint32_t safe_div_uint32_int64(uint32_t a, int64_t b)
1697 {
1698     // Follow original SafeInt logic for this case
1699     if (b == 0) // div 0 always a problem
1700     {
1701         safe_math_fail("safe_math_fail safe_div_uint32_int64");
1702     }
1703 
1704     if (a == 0) // zero divided by anything is zero
1705     {
1706         return 0;
1707     }
1708 
1709     if (b > 0) // if b is positive, just do the math
1710     {
1711         return (uint32_t)(a / b);
1712     }
1713     else // now have to check magnitude
1714     {
1715         uint64_t tmp = safe_abs64(b);
1716 
1717         if (a < tmp)
1718         {
1719             return 0;
1720         }
1721     }
1722 
1723     safe_math_fail("safe_math_fail safe_div_uint32_int64");
1724 }
1725 
1726 static inline bool check_div_uint32_int64(uint32_t a, int64_t b, uint32_t* ret)
1727 {
1728     // Follow original SafeInt logic for this case
1729     if (b == 0) // div 0 always a problem
1730     {
1731         return false;
1732     }
1733 
1734     if (a == 0) // zero divided by anything is zero
1735     {
1736         *ret = 0;
1737         return true;
1738     }
1739 
1740     if (b > 0) // if b is positive, just do the math
1741     {
1742         *ret = (uint32_t)(a / b);
1743         return true;
1744     }
1745     else // now have to check magnitude
1746     {
1747         uint64_t tmp = safe_abs64(b);
1748 
1749         if (a < tmp)
1750         {
1751             *ret = 0;
1752             return true;
1753         }
1754     }
1755 
1756     return false;
1757 }
1758 
1759 static inline uint32_t safe_div_uint32_uint64(uint32_t a, uint64_t b)
1760 {
1761     if (b > 0)
1762     {
1763         return (uint32_t)(a / b);
1764     }
1765     safe_math_fail("safe_math_fail safe_div_uint32_uint64");
1766 }
1767 
1768 static inline bool check_div_uint32_uint64(uint32_t a, uint64_t b, uint32_t* ret)
1769 {
1770     if (b > 0)
1771     {
1772         *ret = (uint32_t)(a / b);
1773         return true;
1774     }
1775     return false;
1776 }
1777 
1778 static inline int64_t safe_div_int64_int32(int64_t a, int32_t b)
1779 {
1780     if(b == 0 || (b == -1 && a == INT64_MIN))
1781         safe_math_fail("safe_math_fail safe_div_int64_int32");
1782 
1783     return a / b;
1784 }
1785 
1786 static inline bool check_div_int64_int32(int64_t a, int32_t b, int64_t* ret)
1787 {
1788     if (b == 0 || (b == -1 && a == INT64_MIN))
1789         return false;
1790 
1791     *ret = a / b;
1792     return true;
1793 }
1794 
1795 static inline int64_t safe_div_int64_uint32(int64_t a, uint32_t b)
1796 {
1797     if (b == 0)
1798         safe_math_fail("safe_math_fail safe_div_int64_int32");
1799 
1800     return a / b;
1801 }
1802 
1803 static inline bool check_div_int64_uint32(int64_t a, uint32_t b, int64_t* ret)
1804 {
1805     if (b == 0)
1806         return false;
1807 
1808     *ret = a / b;
1809     return true;
1810 }
1811 
1812 static inline int64_t safe_div_int64_int64(int64_t a, int64_t b)
1813 {
1814     if (b == 0 || (b == -1 && a == INT64_MIN))
1815         safe_math_fail("safe_math_fail safe_div_int64_int32");
1816 
1817     return a / b;
1818 }
1819 
1820 static inline bool check_div_int64_int64(int64_t a, int64_t b, int64_t* ret)
1821 {
1822     if (b == 0 || (b == -1 && a == INT64_MIN))
1823         return false;
1824 
1825     *ret = a / b;
1826     return true;
1827 
1828 }
1829 
1830 static inline int64_t safe_div_int64_uint64(int64_t a, uint64_t b)
1831 {
1832     if (b == 0)
1833         safe_math_fail("safe_math_fail safe_div_int64_int32");
1834 
1835     if(a >= 0)
1836     {
1837         return (int64_t)((uint64_t)a / b);
1838     }
1839     else
1840     {
1841         // Need to get the magnitude, divide, and then negate
1842         uint64_t tmp = safe_abs64(a);
1843         tmp /= b;
1844         return negate64((int64_t)tmp);
1845     }
1846 }
1847 
1848 static inline bool check_div_int64_uint64(int64_t a, uint64_t b, int64_t* ret)
1849 {
1850     if (b == 0)
1851         return false;
1852 
1853     if(a >= 0)
1854     {
1855         *ret = (int64_t)((uint64_t)a / b);
1856     }
1857     else
1858     {
1859         // Need to get the magnitude, divide, and then negate
1860         uint64_t tmp = safe_abs64(a);
1861         tmp /= b;
1862         *ret = negate64((int64_t)tmp);
1863     }
1864         return true;
1865 }
1866 
1867 static inline uint64_t safe_div_uint64_int32(uint64_t a, int32_t b)
1868 {
1869     // Follow original SafeInt logic for this case
1870     if (b == 0) // div 0 always a problem
1871     {
1872         safe_math_fail("safe_math_fail safe_div_int64_int32");
1873     }
1874 
1875     if (a == 0) // zero divided by anything is zero
1876     {
1877         return 0;
1878     }
1879 
1880     if (b > 0) // if b is positive, just do the math
1881     {
1882         return a / (uint64_t)b;
1883     }
1884     else // now have to check magnitude
1885     {
1886         uint32_t tmp = safe_abs32(b);
1887 
1888         if (a < tmp)
1889         {
1890             return 0;
1891         }
1892     }
1893 
1894     safe_math_fail("safe_math_fail safe_div_int64_int32");
1895 }
1896 
1897 static inline bool check_div_uint64_int32(uint64_t a, int32_t b, uint64_t* ret)
1898 {
1899     // Follow original SafeInt logic for this case
1900     if (b == 0) // div 0 always a problem
1901     {
1902         return false;
1903     }
1904 
1905     if (a == 0) // zero divided by anything is zero
1906     {
1907         *ret = 0;
1908         return true;
1909     }
1910 
1911     if (b > 0) // if b is positive, just do the math
1912     {
1913         *ret = a / (uint64_t)b;
1914         return true;
1915     }
1916     else // now have to check magnitude
1917     {
1918         uint32_t tmp = safe_abs32(b);
1919 
1920         if (a < tmp)
1921         {
1922             *ret = 0;
1923             return true;
1924         }
1925     }
1926 
1927     return false;
1928 }
1929 
1930 static inline uint64_t safe_div_uint64_uint32(uint64_t a, uint32_t b)
1931 {
1932     if (b != 0)
1933         return a / b;
1934 
1935     safe_math_fail("safe_math_fail safe_div_int64_uint32");
1936 }
1937 
1938 static inline bool check_div_uint64_uint32(uint64_t a, uint32_t b, uint64_t* ret)
1939 {
1940     if (b != 0)
1941     {
1942         *ret = a / b;
1943         return true;
1944     }
1945     
1946     return false;
1947 }
1948 
1949 static inline uint64_t safe_div_uint64_int64(uint64_t a, int64_t b)
1950 {
1951     // Follow original SafeInt logic for this case
1952     if (b == 0) // div 0 always a problem
1953     {
1954         safe_math_fail("safe_math_fail safe_div_int64_int32");
1955     }
1956 
1957     if (a == 0) // zero divided by anything is zero
1958     {
1959         return 0;
1960     }
1961 
1962     if (b > 0) // if b is positive, just do the math
1963     {
1964         return a / (uint64_t)b;
1965     }
1966     else // now have to check magnitude
1967     {
1968         uint64_t tmp = safe_abs64(b);
1969 
1970         if (a < tmp)
1971         {
1972             return 0;
1973         }
1974     }
1975 
1976     safe_math_fail("safe_math_fail safe_div_int64_int32");
1977 }
1978 
1979 static inline bool check_div_uint64_int64(uint64_t a, int64_t b, uint64_t* ret)
1980 {
1981     // Follow original SafeInt logic for this case
1982     if (b == 0) // div 0 always a problem
1983     {
1984         return false;
1985     }
1986 
1987     if (a == 0) // zero divided by anything is zero
1988     {
1989         *ret = 0;
1990         return true;
1991     }
1992 
1993     if (b > 0) // if b is positive, just do the math
1994     {
1995         *ret = a / (uint64_t)b;
1996         return true;
1997     }
1998     else // now have to check magnitude
1999     {
2000         uint64_t tmp = safe_abs64(b);
2001 
2002         if (a < tmp)
2003         {
2004             *ret = 0;
2005             return true;
2006         }
2007     }
2008 
2009     return false;
2010 }
2011 
2012 static inline uint64_t safe_div_uint64_uint64(uint64_t a, uint64_t b)
2013 {
2014     if (b != 0)
2015         return a / b;
2016 
2017     safe_math_fail("safe_math_fail safe_div_int64_uint32");
2018 }
2019 
2020 static inline bool check_div_uint64_uint64(uint64_t a, uint64_t b, uint64_t* ret)
2021 {
2022     if (b != 0)
2023     {
2024         *ret = a / b;
2025         return true;
2026     }
2027 
2028     return false;
2029 }
2030 
2031 static inline int32_t safe_sub_int32_int32(int32_t a, int32_t b)
2032 {
2033     int64_t tmp = (int64_t)a - (int64_t)b;
2034     return safe_cast_int32_int64(tmp);
2035 }
2036 
2037 static inline bool check_sub_int32_int32(int32_t a, int32_t b, int32_t* ret)
2038 {
2039     int64_t tmp = (int64_t)a - (int64_t)b;
2040     *ret = (int32_t)tmp;
2041     return check_cast_int32_int64(tmp) == 0;
2042 }
2043 
2044 static inline int32_t safe_sub_int32_uint32(int32_t a, uint32_t b)
2045 {
2046     int64_t tmp = (int64_t)a - (int64_t)b;
2047     return safe_cast_int32_int64(tmp);
2048 }
2049 
2050 static inline bool check_sub_int32_uint32(int32_t a, uint32_t b, int32_t* ret)
2051 {
2052     int64_t tmp = (int64_t)a - (int64_t)b;
2053     *ret = (int32_t)tmp;
2054     return check_cast_int32_int64(tmp) == 0;
2055 }
2056 
2057 static inline int32_t safe_sub_int32_int64(int32_t a, int64_t b)
2058 {
2059     // We have 4 fairly complex cases:
2060     // lhs positive, rhs positive - rhs could be larger than lhs can represent
2061     // lhs positive, rhs negative - additive case - check tmp >= lhs and tmp > max int
2062     // lhs negative, rhs positive - check tmp <= lhs and tmp < min int
2063     // lhs negative, rhs negative - addition cannot internally overflow, check against max
2064 
2065     int64_t tmp = (int64_t)((uint64_t)a - (uint64_t)b);
2066 
2067     if (a >= 0)
2068     {
2069         // first case
2070         if (b >= 0)
2071         {
2072             if (tmp >= INT32_MIN)
2073             {
2074                 return (int32_t)tmp;
2075             }
2076         }
2077         else
2078         {
2079             // second case
2080             if (tmp >= a && tmp <= INT32_MAX)
2081             {
2082                 return (int32_t)tmp;
2083             }
2084         }
2085     }
2086     else
2087     {
2088         // lhs < 0
2089         // third case
2090         if (b >= 0)
2091         {
2092             if (tmp <= a && tmp >= INT32_MIN)
2093             {
2094                 return (int32_t)tmp;
2095             }
2096         }
2097         else
2098         {
2099             // fourth case
2100             if (tmp <= INT32_MAX)
2101             {
2102                 return (int32_t)tmp;
2103             }
2104         }
2105     }
2106 
2107     safe_math_fail("safe_math_fail safe_sub_int32_int64");
2108 }
2109 
2110 static inline bool check_sub_int32_int64(int32_t a, int64_t b, int32_t* ret)
2111 {
2112     // See above for documentation
2113     int64_t tmp = (int64_t)((uint64_t)a - (uint64_t)b);
2114 
2115     if (a >= 0)
2116     {
2117         // first case
2118         if (b >= 0)
2119         {
2120             if (tmp >= INT32_MIN)
2121             {
2122                 *ret = (int32_t)tmp;
2123                 return true;
2124             }
2125         }
2126         else
2127         {
2128             // second case
2129             if (tmp >= a && tmp <= INT32_MAX)
2130             {
2131                 *ret = (int32_t)tmp;
2132                 return true;
2133             }
2134         }
2135     }
2136     else
2137     {
2138         // lhs < 0
2139         // third case
2140         if (b >= 0)
2141         {
2142             if (tmp <= a && tmp >= INT32_MIN)
2143             {
2144                 *ret = (int32_t)tmp;
2145                 return true;
2146             }
2147         }
2148         else
2149         {
2150             // fourth case
2151             if (tmp <= INT32_MAX)
2152             {
2153                 *ret = (int32_t)tmp;
2154                 return true;
2155             }
2156         }
2157     }
2158 
2159     return false;
2160 }
2161 
2162 static inline int32_t safe_sub_int32_uint64(int32_t a, uint64_t b)
2163 {
2164     // We need the absolute value of INT32_MIN
2165     // This will give it to us without extraneous compiler warnings
2166     const uint64_t AbsMinInt32 = (uint64_t)INT32_MAX + 1;
2167 
2168     if (a < 0)
2169     {
2170         if (b <= AbsMinInt32 - safe_abs32(a))
2171         {
2172             return (int32_t)(a - (int64_t)b);
2173         }
2174     }
2175     else
2176     {
2177         if (b <= AbsMinInt32 + (uint64_t)a)
2178         {
2179             return (int32_t)(a - (int64_t)b);
2180         }
2181     }
2182 
2183     safe_math_fail("safe_math_fail safe_sub_int32_uint64");
2184 }
2185 
2186 static inline bool check_sub_int32_uint64(int32_t a, uint64_t b, int32_t* ret)
2187 {
2188     // We need the absolute value of INT32_MIN
2189     // This will give it to us without extraneous compiler warnings
2190     const uint64_t AbsMinInt32 = (uint64_t)INT32_MAX + 1;
2191 
2192     if (a < 0)
2193     {
2194         if (b <= AbsMinInt32 - safe_abs32(a))
2195         {
2196             *ret = (int32_t)(a - (int64_t)b);
2197             return true;
2198         }
2199     }
2200     else
2201     {
2202         if (b <= AbsMinInt32 + (uint64_t)a)
2203         {
2204             *ret = (int32_t)((int64_t)a - (int64_t)b);
2205             return true;
2206         }
2207     }
2208 
2209     return false;
2210 }
2211 
2212 static inline uint32_t safe_sub_uint32_int32(uint32_t a, int32_t b)
2213 {
2214     int64_t tmp = (int64_t)a - (int64_t)b;
2215     return safe_cast_uint32_int64(tmp);
2216 }
2217 
2218 static inline bool check_sub_uint32_int32(uint32_t a, int32_t b, uint32_t* ret)
2219 {
2220     int64_t tmp = (int64_t)a - (int64_t)b;
2221     *ret = (uint32_t)tmp;
2222     return check_cast_uint32_int64(tmp) == 0;
2223 }
2224 
2225 static inline uint32_t safe_sub_uint32_uint32(uint32_t a, uint32_t b)
2226 {
2227     if (a >= b)
2228         return a - b;
2229 
2230     safe_math_fail("safe_math_fail safe_sub_uint32_uint32");
2231 }
2232 
2233 static inline bool check_sub_uint32_uint32(uint32_t a, uint32_t b, uint32_t* ret)
2234 {
2235     if (a >= b)
2236     {
2237         *ret = a - b;
2238         return true;
2239     }
2240 
2241     return false;
2242 }
2243 
2244 static inline uint32_t safe_sub_uint32_int64(uint32_t a, int64_t b)
2245 {
2246     // must first see if rhs is positive or negative
2247     if (b >= 0)
2248     {
2249         if ((uint64_t)b <= a)
2250         {
2251             return (uint32_t)(a - (uint32_t)b);
2252         }
2253     }
2254     else
2255     {
2256         // we're now effectively adding
2257         // since lhs is 32-bit, and rhs cannot exceed 2^63
2258         // this addition cannot overflow
2259         uint64_t tmp = a + (uint64_t)negate64(b); // negation safe
2260 
2261         // but we could exceed UINT32_MAX
2262         if (tmp <= UINT32_MAX)
2263         {
2264             return (uint32_t)tmp;
2265         }
2266     }
2267 
2268     safe_math_fail("safe_math_fail safe_sub_uint32_int64");
2269 }
2270 
2271 static inline bool check_sub_uint32_int64(uint32_t a, int64_t b, uint32_t* ret)
2272 {
2273     // must first see if rhs is positive or negative
2274     if (b >= 0)
2275     {
2276         if ((uint64_t)b <= a)
2277         {
2278             *ret = (uint32_t)(a - (uint32_t)b);
2279             return true;
2280         }
2281     }
2282     else
2283     {
2284         // we're now effectively adding
2285         // since lhs is 32-bit, and rhs cannot exceed 2^63
2286         // this addition cannot overflow
2287         uint64_t tmp = a + (uint64_t)negate64(b); // negation safe
2288 
2289         // but we could exceed UINT32_MAX
2290         if (tmp <= UINT32_MAX)
2291         {
2292             *ret = (uint32_t)tmp;
2293             return true;
2294         }
2295     }
2296 
2297     return false;
2298 }
2299 
2300 static inline uint32_t safe_sub_uint32_uint64(uint32_t a, uint64_t b)
2301 {
2302     if (a >= b)
2303         return (uint32_t)(a - b);
2304 
2305     safe_math_fail("safe_math_fail safe_sub_uint32_uint64");
2306 }
2307 
2308 static inline bool check_sub_uint32_uint64(uint32_t a, uint64_t b, uint32_t* ret)
2309 {
2310     if (a >= b)
2311     {
2312         *ret = (uint32_t)(a - b);
2313         return true;
2314     }
2315     return false;
2316 }
2317 
2318 static inline int64_t safe_sub_int64_int32(int64_t a, int32_t b)
2319 {
2320     // we have essentially 4 cases:
2321     //
2322     // 1) lhs positive, rhs positive - overflow not possible
2323     // 2) lhs positive, rhs negative - equivalent to addition - result >= lhs or error
2324     // 3) lhs negative, rhs positive - check result <= lhs
2325     // 4) lhs negative, rhs negative - overflow not possible
2326 
2327     int64_t tmp = (int64_t)((uint64_t)a - (uint64_t)b);
2328 
2329     // Note - ideally, we can order these so that true conditionals
2330     // lead to success, which enables better pipelining
2331     // It isn't practical here
2332     if ((a >= 0 && b < 0 && tmp < a) || // condition 2
2333         (b >= 0 && tmp > a))              // condition 3
2334     {
2335         safe_math_fail("safe_math_fail safe_sub_int64_int32");
2336     }
2337 
2338     return tmp;
2339 }
2340 
2341 static inline bool check_sub_int64_int32(int64_t a, int32_t b, int64_t* ret)
2342 {
2343     int64_t tmp = (int64_t)((uint64_t)a - (uint64_t)b);
2344 
2345     // Note - ideally, we can order these so that true conditionals
2346     // lead to success, which enables better pipelining
2347     // It isn't practical here
2348     if ((a >= 0 && b < 0 && tmp < a) || // condition 2
2349         (b >= 0 && tmp > a))              // condition 3
2350     {
2351         return false;
2352     }
2353 
2354     *ret = tmp;
2355     return true;
2356 }
2357 
2358 static inline int64_t safe_sub_int64_uint32(int64_t a, uint32_t b)
2359 {
2360     // lhs is a 64-bit int, rhs unsigned int32 or smaller
2361     // perform test as unsigned to prevent unwanted optimizations
2362     uint64_t tmp = (uint64_t)a - (uint64_t)b;
2363 
2364     if ((int64_t)tmp <= a)
2365     {
2366         return (int64_t)tmp;
2367     }
2368 
2369     safe_math_fail("safe_math_fail safe_sub_int64_int64");
2370 }
2371 
2372 static inline bool check_sub_int64_uint32(int64_t a, uint32_t b, int64_t* ret)
2373 {
2374     uint64_t tmp = (uint64_t)a - (uint64_t)b;
2375 
2376     if ((int64_t)tmp <= a)
2377     {
2378         *ret = (int64_t)tmp;
2379         return true;
2380     }
2381 
2382     return false;
2383 }
2384 
2385 static inline int64_t safe_sub_int64_int64(int64_t a, int64_t b)
2386 {
2387     // we have essentially 4 cases:
2388     //
2389     // 1) lhs positive, rhs positive - overflow not possible
2390     // 2) lhs positive, rhs negative - equivalent to addition - result >= lhs or error
2391     // 3) lhs negative, rhs positive - check result <= lhs
2392     // 4) lhs negative, rhs negative - overflow not possible
2393 
2394     int64_t tmp = (int64_t)((uint64_t)a - (uint64_t)b);
2395 
2396     // Note - ideally, we can order these so that true conditionals
2397     // lead to success, which enables better pipelining
2398     // It isn't practical here
2399     if ((a >= 0 && b < 0 && tmp < a) || // condition 2
2400         (b >= 0 && tmp > a))              // condition 3
2401     {
2402         safe_math_fail("safe_math_fail safe_sub_int64_int64");
2403     }
2404 
2405     return tmp;
2406 }
2407 
2408 static inline bool check_sub_int64_int64(int64_t a, int64_t b, int64_t* ret)
2409 {
2410     int64_t tmp = (int64_t)((uint64_t)a - (uint64_t)b);
2411 
2412     // Note - ideally, we can order these so that true conditionals
2413     // lead to success, which enables better pipelining
2414     // It isn't practical here
2415     if ((a >= 0 && b < 0 && tmp < a) || // condition 2
2416         (b >= 0 && tmp > a))              // condition 3
2417     {
2418         return false;
2419     }
2420 
2421     *ret = tmp;
2422     return true;
2423 }
2424 
2425 static inline int64_t safe_sub_int64_uint64(int64_t a, uint64_t b)
2426 {
2427     // if we subtract, and it gets larger, there's a problem
2428     // Perform test as unsigned to prevent unwanted optimizations
2429     uint64_t tmp = (uint64_t)a - b;
2430 
2431     if ((int64_t)tmp <= a)
2432     {
2433         return (int64_t)tmp;
2434     }
2435 
2436     safe_math_fail("safe_math_fail safe_sub_int64_uint64");
2437 }
2438 
2439 static inline bool check_sub_int64_uint64(int64_t a, uint64_t b, int64_t* ret)
2440 {
2441     uint64_t tmp = (uint64_t)a - b;
2442     *ret = (int64_t)tmp;
2443 
2444     return ((int64_t)tmp <= a);
2445 }
2446 
2447 static inline uint64_t safe_sub_uint64_int32(uint64_t a, int32_t b)
2448 {
2449     // lhs is an uint64_t, rhs signed
2450     // must first see if rhs is positive or negative
2451     if (b >= 0)
2452     {
2453         if ((uint64_t)b <= a)
2454         {
2455             return (uint64_t)(a - (uint64_t)b);
2456         }
2457     }
2458     else
2459     {
2460         uint64_t tmp = a;
2461         // we're now effectively adding
2462         uint64_t result = a + safe_abs64(b);
2463 
2464         if (result >= tmp)
2465             return result;
2466     }
2467 
2468     safe_math_fail("safe_math_fail safe_sub_uint64_int32");
2469 }
2470 
2471 static inline bool check_sub_uint64_int32(uint64_t a, int32_t b, uint64_t* ret)
2472 {
2473     if (b >= 0)
2474     {
2475         if ((uint64_t)b <= a)
2476         {
2477             *ret = (uint64_t)(a - (uint64_t)b);
2478             return true;
2479         }
2480     }
2481     else
2482     {
2483         uint64_t tmp = a;
2484         // we're now effectively adding
2485         uint64_t result = a + safe_abs64(b);
2486 
2487         if (result >= tmp)
2488         {
2489             *ret = result;
2490             return true;
2491         }
2492     }
2493 
2494     return false;
2495 }
2496 
2497 static inline uint64_t safe_sub_uint64_uint32(uint64_t a, uint32_t b)
2498 {
2499     uint64_t tmp = a - b;
2500 
2501     if (tmp <= a)
2502         return tmp;
2503 
2504     safe_math_fail("safe_math_fail safe_sub_uint64_uint32");
2505 }
2506 
2507 static inline bool check_sub_uint64_uint32(uint64_t a, uint32_t b, uint64_t* ret)
2508 {
2509     uint64_t tmp = a - b;
2510     *ret = tmp;
2511     return (tmp <= a);
2512 }
2513 
2514 static inline uint64_t safe_sub_uint64_int64(uint64_t a, int64_t b)
2515 {
2516     uint64_t result = 0;
2517 
2518     // must first see if rhs is positive or negative
2519     if (b >= 0)
2520     {
2521         if ((uint64_t)b <= a)
2522         {
2523             return (a - (uint64_t)b);
2524         }
2525     }
2526     else
2527     {
2528         // we're now effectively adding
2529         result = a + safe_abs64(b);
2530 
2531         if (result >= a)
2532             return result;
2533     }
2534 
2535     safe_math_fail("safe_math_fail safe_sub_uint64_int64");
2536 }
2537 
2538 static inline bool check_sub_uint64_int64(uint64_t a, int64_t b, uint64_t* ret)
2539 {
2540     uint64_t result = 0;
2541 
2542     // must first see if rhs is positive or negative
2543     if (b >= 0)
2544     {
2545         if ((uint64_t)b <= a)
2546         {
2547             *ret = (a - (uint64_t)b);
2548             return true;
2549         }
2550     }
2551     else
2552     {
2553         // we're now effectively adding
2554         result = a + safe_abs64(b);
2555 
2556         if (result >= a)
2557         {
2558             *ret = result;
2559             return true;
2560         }
2561     }
2562 
2563     return false;
2564 }
2565 
2566 static inline uint64_t safe_sub_uint64_uint64(uint64_t a, uint64_t b)
2567 {
2568     uint64_t tmp = a - b;
2569 
2570     if (tmp <= a)
2571         return tmp;
2572 
2573     safe_math_fail("safe_math_fail safe_sub_uint64_uint64");
2574 }
2575 
2576 static inline bool check_sub_uint64_uint64(uint64_t a, uint64_t b, uint64_t* ret)
2577 {
2578     uint64_t tmp = a - b;
2579     *ret = tmp;
2580     return (tmp <= a);
2581 }
2582 
2583 #ifdef __cplusplus
2584 } 
2585 #endif
2586 
2587 #endif // C_SAFE_MATH_IMPL