|
|
|
@ -45,8 +45,72 @@ static inline _Bool __ckd_mul_##suffix(type *r, type a, type b) \ |
|
|
|
return b > 0 && a > (MAX / b); \ |
|
|
|
} |
|
|
|
|
|
|
|
# define __ckd_signed_common(suffix, type, MIN, MAX) \ |
|
|
|
static inline _Bool __ckd_add_##suffix(type *r, type a, type b) \ |
|
|
|
{ \ |
|
|
|
union suffix ua = { .v = a }; \ |
|
|
|
union suffix ub = { .v = b }; \ |
|
|
|
union suffix ur = { .uv = ua.uv + ub.uv }; \ |
|
|
|
*r = ur.v; \ |
|
|
|
if ((b > 0 && a > (MAX - b)) || (b < 0 && a < (MIN - b))) \ |
|
|
|
return 1; \ |
|
|
|
return 0; \ |
|
|
|
} \ |
|
|
|
\ |
|
|
|
static inline _Bool __ckd_sub_##suffix(type *r, type a, type b) \ |
|
|
|
{ \ |
|
|
|
union suffix ua = { .v = a }; \ |
|
|
|
union suffix ub = { .v = b }; \ |
|
|
|
union suffix ur = { .uv = ua.uv - ub.uv }; \ |
|
|
|
*r = ur.v; \ |
|
|
|
if ((b < 0 && a > (MAX + b)) || (b > 0 && a < (MIN + b))) \ |
|
|
|
return 1; \ |
|
|
|
return 0; \ |
|
|
|
} \ |
|
|
|
\ |
|
|
|
static inline _Bool __ckd_mul_##suffix(type *r, type a, type b) \ |
|
|
|
{ \ |
|
|
|
union suffix ua = { .v = a }; \ |
|
|
|
union suffix ub = { .v = b }; \ |
|
|
|
union suffix ur = { .uv = ua.uv * ub.uv }; \ |
|
|
|
*r = ur.v; \ |
|
|
|
if (a > 0) { \ |
|
|
|
if (b > 0) { \ |
|
|
|
if (a > (MAX / b)) return 1; \ |
|
|
|
} else if (b < 0) { \ |
|
|
|
if (b < (MIN / a)) return 1; \ |
|
|
|
} \ |
|
|
|
} else if (a < 0) { \ |
|
|
|
if (b > 0) { \ |
|
|
|
if (a < (MIN / b)) return 1; \ |
|
|
|
} else if (b < 0) { \ |
|
|
|
if (b < (MAX / a)) return 1; \ |
|
|
|
} \ |
|
|
|
} \ |
|
|
|
return 0; \ |
|
|
|
} |
|
|
|
|
|
|
|
# define __ckd_signed(suffix, type, MIN, MAX) \ |
|
|
|
union suffix { \ |
|
|
|
unsigned type uv; \ |
|
|
|
type v; \ |
|
|
|
}; \ |
|
|
|
__ckd_signed_common(suffix, type, MIN, MAX) |
|
|
|
|
|
|
|
# define __ckd_signed_forced(suffix, type, MIN, MAX) \ |
|
|
|
union suffix { \ |
|
|
|
unsigned type uv; \ |
|
|
|
signed type v; \ |
|
|
|
}; \ |
|
|
|
__ckd_signed_common(suffix, signed type, MIN, MAX) |
|
|
|
|
|
|
|
# define __ckd_func(op, r, a, b) \ |
|
|
|
_Generic (*(r), \ |
|
|
|
signed char: __ckd_##op##_sc((signed char *)(r), a, b), \ |
|
|
|
short: __ckd_##op##_ss((short *)(r), a, b), \ |
|
|
|
int: __ckd_##op##_si((int *)(r), a, b), \ |
|
|
|
long: __ckd_##op##_sl((long *)(r), a, b), \ |
|
|
|
long long: __ckd_##op##_sll((long long *)(r), a, b), \ |
|
|
|
unsigned char: __ckd_##op##_uc((unsigned char *)(r), a, b), \ |
|
|
|
unsigned short: __ckd_##op##_us((unsigned short *)(r), a, b), \ |
|
|
|
unsigned int: __ckd_##op##_ui((unsigned int *)(r), a, b), \ |
|
|
|
@ -59,6 +123,12 @@ __ckd_unsigned(ui, unsigned int, UINT_MAX) |
|
|
|
__ckd_unsigned(ul, unsigned long, ULONG_MAX) |
|
|
|
__ckd_unsigned(ull, unsigned long long, ULLONG_MAX) |
|
|
|
|
|
|
|
__ckd_signed_forced(sc, char, SCHAR_MIN, SCHAR_MAX) |
|
|
|
__ckd_signed(ss, short, SHRT_MIN, SHRT_MAX) |
|
|
|
__ckd_signed(si, int, INT_MIN, INT_MAX) |
|
|
|
__ckd_signed(sl, long, LONG_MIN, LONG_MAX) |
|
|
|
__ckd_signed(sll, long long, LLONG_MIN, LLONG_MAX) |
|
|
|
|
|
|
|
# define ckd_add(r, a, b) __ckd_func(add, r, a, b) |
|
|
|
# define ckd_sub(r, a, b) __ckd_func(sub, r, a, b) |
|
|
|
# define ckd_mul(r, a, b) __ckd_func(mul, r, a, b) |
|
|
|
|