1*4882a593Smuzhiyun /* safe_iop 2*4882a593Smuzhiyun * License:: released in to the public domain 3*4882a593Smuzhiyun * Author:: Will Drewry <redpig@dataspill.org> 4*4882a593Smuzhiyun * Copyright 2007,2008 redpig@dataspill.org 5*4882a593Smuzhiyun * Some portions copyright The Android Open Source Project 6*4882a593Smuzhiyun * 7*4882a593Smuzhiyun * Unless required by applicable law or agreed to in writing, software 8*4882a593Smuzhiyun * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS 9*4882a593Smuzhiyun * OF ANY KIND, either express or implied. 10*4882a593Smuzhiyun * 11*4882a593Smuzhiyun * To Do: 12*4882a593Smuzhiyun * - Add varargs style interface for safe_<op>() 13*4882a593Smuzhiyun * - Add support for safe conversion 14*4882a593Smuzhiyun * - Add additional sizes to safe_iopf (currently 32-bit only) 15*4882a593Smuzhiyun * (this will make use of the safe conversion above) 16*4882a593Smuzhiyun * - Add left shift support 17*4882a593Smuzhiyun * - Add more test cases for interfaces (op_mixed) 18*4882a593Smuzhiyun * - Add more tests for edge cases I've missed? and for thoroughness 19*4882a593Smuzhiyun * 20*4882a593Smuzhiyun * History: 21*4882a593Smuzhiyun * = 0.3 22*4882a593Smuzhiyun * - solidified code into a smaller number of macros and functions 23*4882a593Smuzhiyun * - added typeless functions using gcc magic (typeof) 24*4882a593Smuzhiyun * - deprecrated old interfaces (-DSAFE_IOP_COMPAT) 25*4882a593Smuzhiyun * - discover size maximums automagically 26*4882a593Smuzhiyun * - separated test cases for easier understanding 27*4882a593Smuzhiyun * - significantly expanded test cases 28*4882a593Smuzhiyun * - derive type maximums and minimums internally (checked in testing) 29*4882a593Smuzhiyun * = 0.2 30*4882a593Smuzhiyun * - Removed dependence on twos complement arithmetic to allow macro-ized 31*4882a593Smuzhiyun * definitions 32*4882a593Smuzhiyun * - Added (s)size_t support 33*4882a593Smuzhiyun * - Added (u)int8,16,64 support 34*4882a593Smuzhiyun * - Added portable inlining 35*4882a593Smuzhiyun * - Added support for NULL result pointers 36*4882a593Smuzhiyun * - Added support for header-only use (safe_iop.c only needed for safe_iopf) 37*4882a593Smuzhiyun * = 0.1 38*4882a593Smuzhiyun * - Initial release 39*4882a593Smuzhiyun * 40*4882a593Smuzhiyun * Contributors & thanks: 41*4882a593Smuzhiyun * - peter@valchev.net for his review, comments, and enthusiasm 42*4882a593Smuzhiyun * - thanks to Google for contributing some time 43*4882a593Smuzhiyun */ 44*4882a593Smuzhiyun 45*4882a593Smuzhiyun /* This library supplies a set of standard functions for performing and 46*4882a593Smuzhiyun * checking safe integer operations. The code is based on examples from 47*4882a593Smuzhiyun * https://www.securecoding.cert.org/confluence/display/seccode/INT32-C.+Ensure+that+operations+on+signed+integers+do+not+result+in+overflow 48*4882a593Smuzhiyun * 49*4882a593Smuzhiyun * Inline functions are available for specific operations. If the result 50*4882a593Smuzhiyun * pointer is NULL, the function will still return 1 or 0 if it would 51*4882a593Smuzhiyun * or would not overflow. If multiple operations need to be performed, 52*4882a593Smuzhiyun * safe_iopf provides a format-string driven model, but it does not yet support 53*4882a593Smuzhiyun * non-32 bit operations 54*4882a593Smuzhiyun * 55*4882a593Smuzhiyun * NOTE: This code assumes int32_t to be signed. 56*4882a593Smuzhiyun */ 57*4882a593Smuzhiyun #ifndef _SAFE_IOP_H 58*4882a593Smuzhiyun #define _SAFE_IOP_H 59*4882a593Smuzhiyun #include <limits.h> /* for CHAR_BIT */ 60*4882a593Smuzhiyun #include <assert.h> /* for type enforcement */ 61*4882a593Smuzhiyun 62*4882a593Smuzhiyun typedef enum { SAFE_IOP_TYPE_S32 = 1, 63*4882a593Smuzhiyun SAFE_IOP_TYPE_U32, 64*4882a593Smuzhiyun SAFE_IOP_TYPE_DEFAULT = SAFE_IOP_TYPE_S32, 65*4882a593Smuzhiyun } safe_type_t; 66*4882a593Smuzhiyun 67*4882a593Smuzhiyun #define SAFE_IOP_TYPE_PREFIXES "us" 68*4882a593Smuzhiyun 69*4882a593Smuzhiyun /* use a nice prefix :) */ 70*4882a593Smuzhiyun #define __sio(x) OPAQUE_SAFE_IOP_PREFIX_ ## x 71*4882a593Smuzhiyun #define OPAQUE_SAFE_IOP_PREFIX_var(x) __sio(VARIABLE_ ## x) 72*4882a593Smuzhiyun #define OPAQUE_SAFE_IOP_PREFIX_m(x) __sio(MACRO_ ## x) 73*4882a593Smuzhiyun 74*4882a593Smuzhiyun 75*4882a593Smuzhiyun /* A recursive macro which safely multiplies the given type together. 76*4882a593Smuzhiyun * _ptr may be NULL. 77*4882a593Smuzhiyun * mixed types or mixed sizes will unconditionally return 0; 78*4882a593Smuzhiyun */ 79*4882a593Smuzhiyun #define OPAQUE_SAFE_IOP_PREFIX_MACRO_smax(_a) \ 80*4882a593Smuzhiyun ((typeof(_a))(~((typeof(_a)) 1 << ((sizeof(typeof(_a)) * CHAR_BIT) - 1)))) 81*4882a593Smuzhiyun #define OPAQUE_SAFE_IOP_PREFIX_MACRO_smin(_a) \ 82*4882a593Smuzhiyun ((typeof(_a))(-__sio(m)(smax)(_a) - 1)) 83*4882a593Smuzhiyun #define OPAQUE_SAFE_IOP_PREFIX_MACRO_umax(_a) ((typeof(_a))(~((typeof(_a)) 0))) 84*4882a593Smuzhiyun 85*4882a593Smuzhiyun #define OPAQUE_SAFE_IOP_PREFIX_MACRO_type_enforce(__A, __B) \ 86*4882a593Smuzhiyun ((((__sio(m)(smin)(__A) <= ((typeof(__A))0)) && \ 87*4882a593Smuzhiyun (__sio(m)(smin)(__B) <= ((typeof(__B))0))) || \ 88*4882a593Smuzhiyun (((__sio(m)(smin)(__A) > ((typeof(__A))0))) && \ 89*4882a593Smuzhiyun (__sio(m)(smin)(__B) > ((typeof(__B))0)))) && \ 90*4882a593Smuzhiyun (sizeof(typeof(__A)) == sizeof(typeof(__B)))) 91*4882a593Smuzhiyun 92*4882a593Smuzhiyun 93*4882a593Smuzhiyun /* We use a non-void wrapper for assert(). This allows us to factor it away on 94*4882a593Smuzhiyun * -DNDEBUG but still have conditionals test the result (and optionally return 95*4882a593Smuzhiyun * false). 96*4882a593Smuzhiyun */ 97*4882a593Smuzhiyun #if defined(NDEBUG) 98*4882a593Smuzhiyun # define OPAQUE_SAFE_IOP_PREFIX_MACRO_assert(x) (x) 99*4882a593Smuzhiyun #else 100*4882a593Smuzhiyun # define OPAQUE_SAFE_IOP_PREFIX_MACRO_assert(x) ({ assert(x); 1; }) 101*4882a593Smuzhiyun #endif 102*4882a593Smuzhiyun 103*4882a593Smuzhiyun 104*4882a593Smuzhiyun /* Primary interface macros */ 105*4882a593Smuzhiyun /* type checking is compiled out if NDEBUG supplied. */ 106*4882a593Smuzhiyun #define safe_add(_ptr, __a, __b) \ 107*4882a593Smuzhiyun ({ int __sio(var)(ok) = 0; \ 108*4882a593Smuzhiyun typeof(__a) __sio(var)(_a) = (__a); \ 109*4882a593Smuzhiyun typeof(__b) __sio(var)(_b) = (__b); \ 110*4882a593Smuzhiyun typeof(_ptr) __sio(var)(p) = (_ptr); \ 111*4882a593Smuzhiyun if (__sio(m)(assert)(__sio(m)(type_enforce)(__sio(var)(_a), \ 112*4882a593Smuzhiyun __sio(var)(_b)))) { \ 113*4882a593Smuzhiyun if (__sio(m)(smin)(__sio(var)(_a)) <= ((typeof(__sio(var)(_a)))0)) { \ 114*4882a593Smuzhiyun __sio(var)(ok) = safe_sadd(__sio(var)(p), \ 115*4882a593Smuzhiyun __sio(var)(_a), \ 116*4882a593Smuzhiyun __sio(var)(_b)); \ 117*4882a593Smuzhiyun } else { \ 118*4882a593Smuzhiyun __sio(var)(ok) = safe_uadd(__sio(var)(p), \ 119*4882a593Smuzhiyun __sio(var)(_a), \ 120*4882a593Smuzhiyun __sio(var)(_b)); \ 121*4882a593Smuzhiyun } \ 122*4882a593Smuzhiyun } \ 123*4882a593Smuzhiyun __sio(var)(ok); }) 124*4882a593Smuzhiyun 125*4882a593Smuzhiyun #define safe_add3(_ptr, _A, _B, _C) \ 126*4882a593Smuzhiyun ({ typeof(_A) __sio(var)(a) = (_A); \ 127*4882a593Smuzhiyun typeof(_B) __sio(var)(b) = (_B); \ 128*4882a593Smuzhiyun typeof(_C) __sio(var)(c) = (_C); \ 129*4882a593Smuzhiyun typeof(_A) __sio(var)(r) = 0; \ 130*4882a593Smuzhiyun (safe_add(&(__sio(var)(r)), __sio(var)(a), __sio(var)(b)) && \ 131*4882a593Smuzhiyun safe_add((_ptr), __sio(var)(r), __sio(var)(c))); }) 132*4882a593Smuzhiyun 133*4882a593Smuzhiyun #define safe_add4(_ptr, _A, _B, _C, _D) \ 134*4882a593Smuzhiyun ({ typeof(_A) __sio(var)(a) = (_A); \ 135*4882a593Smuzhiyun typeof(_B) __sio(var)(b) = (_B); \ 136*4882a593Smuzhiyun typeof(_C) __sio(var)(c) = (_C); \ 137*4882a593Smuzhiyun typeof(_D) __sio(var)(d) = (_D); \ 138*4882a593Smuzhiyun typeof(_A) __sio(var)(r) = 0; \ 139*4882a593Smuzhiyun (safe_add(&(__sio(var)(r)), __sio(var)(a), __sio(var)(b)) && \ 140*4882a593Smuzhiyun safe_add(&(__sio(var)(r)), __sio(var)(r), __sio(var)(c)) && \ 141*4882a593Smuzhiyun safe_add((_ptr), __sio(var)(r), (__sio(var)(d)))); }) 142*4882a593Smuzhiyun 143*4882a593Smuzhiyun #define safe_add5(_ptr, _A, _B, _C, _D, _E) \ 144*4882a593Smuzhiyun ({ typeof(_A) __sio(var)(a) = (_A); \ 145*4882a593Smuzhiyun typeof(_B) __sio(var)(b) = (_B); \ 146*4882a593Smuzhiyun typeof(_C) __sio(var)(c) = (_C); \ 147*4882a593Smuzhiyun typeof(_D) __sio(var)(d) = (_D); \ 148*4882a593Smuzhiyun typeof(_E) __sio(var)(e) = (_E); \ 149*4882a593Smuzhiyun typeof(_A) __sio(var)(r) = 0; \ 150*4882a593Smuzhiyun (safe_add(&(__sio(var)(r)), __sio(var)(a), __sio(var)(b)) && \ 151*4882a593Smuzhiyun safe_add(&(__sio(var)(r)), __sio(var)(r), __sio(var)(c)) && \ 152*4882a593Smuzhiyun safe_add(&(__sio(var)(r)), __sio(var)(r), __sio(var)(d)) && \ 153*4882a593Smuzhiyun safe_add((_ptr), __sio(var)(r), __sio(var)(e))); }) 154*4882a593Smuzhiyun 155*4882a593Smuzhiyun #define safe_sub(_ptr, __a, __b) \ 156*4882a593Smuzhiyun ({ int __sio(var)(ok) = 0; \ 157*4882a593Smuzhiyun typeof(__a) __sio(var)(_a) = (__a); \ 158*4882a593Smuzhiyun typeof(__b) __sio(var)(_b) = (__b); \ 159*4882a593Smuzhiyun typeof(_ptr) __sio(var)(p) = (_ptr); \ 160*4882a593Smuzhiyun if (__sio(m)(assert)(__sio(m)(type_enforce)(__sio(var)(_a), \ 161*4882a593Smuzhiyun __sio(var)(_b)))) { \ 162*4882a593Smuzhiyun if (__sio(m)(umax)(__sio(var)(_a)) <= ((typeof(__sio(var)(_a)))0)) { \ 163*4882a593Smuzhiyun __sio(var)(ok) = safe_ssub(__sio(var)(p), \ 164*4882a593Smuzhiyun __sio(var)(_a), \ 165*4882a593Smuzhiyun __sio(var)(_b)); \ 166*4882a593Smuzhiyun } else { \ 167*4882a593Smuzhiyun __sio(var)(ok) = safe_usub(__sio(var)(p), \ 168*4882a593Smuzhiyun __sio(var)(_a), \ 169*4882a593Smuzhiyun __sio(var)(_b)); \ 170*4882a593Smuzhiyun } \ 171*4882a593Smuzhiyun } \ 172*4882a593Smuzhiyun __sio(var)(ok); }) 173*4882a593Smuzhiyun 174*4882a593Smuzhiyun /* These are sequentially performed */ 175*4882a593Smuzhiyun #define safe_sub3(_ptr, _A, _B, _C) \ 176*4882a593Smuzhiyun ({ typeof(_A) __sio(var)(a) = (_A); \ 177*4882a593Smuzhiyun typeof(_B) __sio(var)(b) = (_B); \ 178*4882a593Smuzhiyun typeof(_C) __sio(var)(c) = (_C); \ 179*4882a593Smuzhiyun typeof(_A) __sio(var)(r) = 0; \ 180*4882a593Smuzhiyun (safe_sub(&(__sio(var)(r)), __sio(var)(a), __sio(var)(b)) && \ 181*4882a593Smuzhiyun safe_sub((_ptr), __sio(var)(r), __sio(var)(c))); }) 182*4882a593Smuzhiyun 183*4882a593Smuzhiyun #define safe_sub4(_ptr, _A, _B, _C, _D) \ 184*4882a593Smuzhiyun ({ typeof(_A) __sio(var)(a) = (_A); \ 185*4882a593Smuzhiyun typeof(_B) __sio(var)(b) = (_B); \ 186*4882a593Smuzhiyun typeof(_C) __sio(var)(c) = (_C); \ 187*4882a593Smuzhiyun typeof(_D) __sio(var)(d) = (_D); \ 188*4882a593Smuzhiyun typeof(_A) __sio(var)(r) = 0; \ 189*4882a593Smuzhiyun (safe_sub(&(__sio(var)(r)), __sio(var)(a), __sio(var)(b)) && \ 190*4882a593Smuzhiyun safe_sub(&(__sio(var)(r)), __sio(var)(r), __sio(var)(c)) && \ 191*4882a593Smuzhiyun safe_sub((_ptr), __sio(var)(r), (__sio(var)(d)))); }) 192*4882a593Smuzhiyun 193*4882a593Smuzhiyun #define safe_sub5(_ptr, _A, _B, _C, _D, _E) \ 194*4882a593Smuzhiyun ({ typeof(_A) __sio(var)(a) = (_A); \ 195*4882a593Smuzhiyun typeof(_B) __sio(var)(b) = (_B); \ 196*4882a593Smuzhiyun typeof(_C) __sio(var)(c) = (_C); \ 197*4882a593Smuzhiyun typeof(_D) __sio(var)(d) = (_D); \ 198*4882a593Smuzhiyun typeof(_E) __sio(var)(e) = (_E); \ 199*4882a593Smuzhiyun typeof(_A) __sio(var)(r) = 0; \ 200*4882a593Smuzhiyun (safe_sub(&(__sio(var)(r)), __sio(var)(a), __sio(var)(b)) && \ 201*4882a593Smuzhiyun safe_sub(&(__sio(var)(r)), __sio(var)(r), __sio(var)(c)) && \ 202*4882a593Smuzhiyun safe_sub(&(__sio(var)(r)), __sio(var)(r), __sio(var)(d)) && \ 203*4882a593Smuzhiyun safe_sub((_ptr), __sio(var)(r), __sio(var)(e))); }) 204*4882a593Smuzhiyun 205*4882a593Smuzhiyun 206*4882a593Smuzhiyun 207*4882a593Smuzhiyun #define safe_mul(_ptr, __a, __b) \ 208*4882a593Smuzhiyun ({ int __sio(var)(ok) = 0; \ 209*4882a593Smuzhiyun typeof(__a) __sio(var)(_a) = (__a); \ 210*4882a593Smuzhiyun typeof(__b) __sio(var)(_b) = (__b); \ 211*4882a593Smuzhiyun typeof(_ptr) __sio(var)(p) = (_ptr); \ 212*4882a593Smuzhiyun if (__sio(m)(assert)(__sio(m)(type_enforce)(__sio(var)(_a), \ 213*4882a593Smuzhiyun __sio(var)(_b)))) { \ 214*4882a593Smuzhiyun if (__sio(m)(umax)(__sio(var)(_a)) <= ((typeof(__sio(var)(_a)))0)) { \ 215*4882a593Smuzhiyun __sio(var)(ok) = safe_smul(__sio(var)(p), \ 216*4882a593Smuzhiyun __sio(var)(_a), \ 217*4882a593Smuzhiyun __sio(var)(_b)); \ 218*4882a593Smuzhiyun } else { \ 219*4882a593Smuzhiyun __sio(var)(ok) = safe_umul(__sio(var)(p), \ 220*4882a593Smuzhiyun __sio(var)(_a), \ 221*4882a593Smuzhiyun __sio(var)(_b)); \ 222*4882a593Smuzhiyun } \ 223*4882a593Smuzhiyun } \ 224*4882a593Smuzhiyun __sio(var)(ok); }) 225*4882a593Smuzhiyun 226*4882a593Smuzhiyun #define safe_mul3(_ptr, _A, _B, _C) \ 227*4882a593Smuzhiyun ({ typeof(_A) __sio(var)(a) = (_A); \ 228*4882a593Smuzhiyun typeof(_B) __sio(var)(b) = (_B); \ 229*4882a593Smuzhiyun typeof(_C) __sio(var)(c) = (_C); \ 230*4882a593Smuzhiyun typeof(_A) __sio(var)(r) = 0; \ 231*4882a593Smuzhiyun (safe_mul(&(__sio(var)(r)), __sio(var)(a), __sio(var)(b)) && \ 232*4882a593Smuzhiyun safe_mul((_ptr), __sio(var)(r), __sio(var)(c))); }) 233*4882a593Smuzhiyun 234*4882a593Smuzhiyun #define safe_mul4(_ptr, _A, _B, _C, _D) \ 235*4882a593Smuzhiyun ({ typeof(_A) __sio(var)(a) = (_A); \ 236*4882a593Smuzhiyun typeof(_B) __sio(var)(b) = (_B); \ 237*4882a593Smuzhiyun typeof(_C) __sio(var)(c) = (_C); \ 238*4882a593Smuzhiyun typeof(_D) __sio(var)(d) = (_D); \ 239*4882a593Smuzhiyun typeof(_A) __sio(var)(r) = 0; \ 240*4882a593Smuzhiyun (safe_mul(&(__sio(var)(r)), __sio(var)(a), __sio(var)(b)) && \ 241*4882a593Smuzhiyun safe_mul(&(__sio(var)(r)), __sio(var)(r), __sio(var)(c)) && \ 242*4882a593Smuzhiyun safe_mul((_ptr), __sio(var)(r), (__sio(var)(d)))); }) 243*4882a593Smuzhiyun 244*4882a593Smuzhiyun #define safe_mul5(_ptr, _A, _B, _C, _D, _E) \ 245*4882a593Smuzhiyun ({ typeof(_A) __sio(var)(a) = (_A); \ 246*4882a593Smuzhiyun typeof(_B) __sio(var)(b) = (_B); \ 247*4882a593Smuzhiyun typeof(_C) __sio(var)(c) = (_C); \ 248*4882a593Smuzhiyun typeof(_D) __sio(var)(d) = (_D); \ 249*4882a593Smuzhiyun typeof(_E) __sio(var)(e) = (_E); \ 250*4882a593Smuzhiyun typeof(_A) __sio(var)(r) = 0; \ 251*4882a593Smuzhiyun (safe_mul(&(__sio(var)(r)), __sio(var)(a), __sio(var)(b)) && \ 252*4882a593Smuzhiyun safe_mul(&(__sio(var)(r)), __sio(var)(r), __sio(var)(c)) && \ 253*4882a593Smuzhiyun safe_mul(&(__sio(var)(r)), __sio(var)(r), __sio(var)(d)) && \ 254*4882a593Smuzhiyun safe_mul((_ptr), __sio(var)(r), __sio(var)(e))); }) 255*4882a593Smuzhiyun 256*4882a593Smuzhiyun #define safe_div(_ptr, __a, __b) \ 257*4882a593Smuzhiyun ({ int __sio(var)(ok) = 0; \ 258*4882a593Smuzhiyun typeof(__a) __sio(var)(_a) = (__a); \ 259*4882a593Smuzhiyun typeof(__b) __sio(var)(_b) = (__b); \ 260*4882a593Smuzhiyun typeof(_ptr) __sio(var)(p) = (_ptr); \ 261*4882a593Smuzhiyun if (__sio(m)(assert)(__sio(m)(type_enforce)(__sio(var)(_a), \ 262*4882a593Smuzhiyun __sio(var)(_b)))) { \ 263*4882a593Smuzhiyun if (__sio(m)(umax)(__sio(var)(_a)) <= ((typeof(__sio(var)(_a)))0)) { \ 264*4882a593Smuzhiyun __sio(var)(ok) = safe_sdiv(__sio(var)(p), \ 265*4882a593Smuzhiyun __sio(var)(_a), \ 266*4882a593Smuzhiyun __sio(var)(_b)); \ 267*4882a593Smuzhiyun } else { \ 268*4882a593Smuzhiyun __sio(var)(ok) = safe_udiv(__sio(var)(p), \ 269*4882a593Smuzhiyun __sio(var)(_a), \ 270*4882a593Smuzhiyun __sio(var)(_b)); \ 271*4882a593Smuzhiyun } \ 272*4882a593Smuzhiyun } \ 273*4882a593Smuzhiyun __sio(var)(ok); }) 274*4882a593Smuzhiyun 275*4882a593Smuzhiyun #define safe_div3(_ptr, _A, _B, _C) \ 276*4882a593Smuzhiyun ({ typeof(_A) __sio(var)(a) = (_A); \ 277*4882a593Smuzhiyun typeof(_B) __sio(var)(b) = (_B); \ 278*4882a593Smuzhiyun typeof(_C) __sio(var)(c) = (_C); \ 279*4882a593Smuzhiyun typeof(_A) __sio(var)(r) = 0; \ 280*4882a593Smuzhiyun (safe_div(&(__sio(var)(r)), __sio(var)(a), __sio(var)(b)) && \ 281*4882a593Smuzhiyun safe_div((_ptr), __sio(var)(r), __sio(var)(c))); }) 282*4882a593Smuzhiyun 283*4882a593Smuzhiyun #define safe_div4(_ptr, _A, _B, _C, _D) \ 284*4882a593Smuzhiyun ({ typeof(_A) __sio(var)(a) = (_A); \ 285*4882a593Smuzhiyun typeof(_B) __sio(var)(b) = (_B); \ 286*4882a593Smuzhiyun typeof(_C) __sio(var)(c) = (_C); \ 287*4882a593Smuzhiyun typeof(_D) __sio(var)(d) = (_D); \ 288*4882a593Smuzhiyun typeof(_A) __sio(var)(r) = 0; \ 289*4882a593Smuzhiyun (safe_div(&(__sio(var)(r)), __sio(var)(a), __sio(var)(b)) && \ 290*4882a593Smuzhiyun safe_div(&(__sio(var)(r)), __sio(var)(r), __sio(var)(c)) && \ 291*4882a593Smuzhiyun safe_div((_ptr), __sio(var)(r), (__sio(var)(d)))); }) 292*4882a593Smuzhiyun 293*4882a593Smuzhiyun #define safe_div5(_ptr, _A, _B, _C, _D, _E) \ 294*4882a593Smuzhiyun ({ typeof(_A) __sio(var)(a) = (_A); \ 295*4882a593Smuzhiyun typeof(_B) __sio(var)(b) = (_B); \ 296*4882a593Smuzhiyun typeof(_C) __sio(var)(c) = (_C); \ 297*4882a593Smuzhiyun typeof(_D) __sio(var)(d) = (_D); \ 298*4882a593Smuzhiyun typeof(_E) __sio(var)(e) = (_E); \ 299*4882a593Smuzhiyun typeof(_A) __sio(var)(r) = 0; \ 300*4882a593Smuzhiyun (safe_div(&(__sio(var)(r)), __sio(var)(a), __sio(var)(b)) && \ 301*4882a593Smuzhiyun safe_div(&(__sio(var)(r)), __sio(var)(r), __sio(var)(c)) && \ 302*4882a593Smuzhiyun safe_div(&(__sio(var)(r)), __sio(var)(r), __sio(var)(d)) && \ 303*4882a593Smuzhiyun safe_div((_ptr), __sio(var)(r), __sio(var)(e))); }) 304*4882a593Smuzhiyun 305*4882a593Smuzhiyun #define safe_mod(_ptr, __a, __b) \ 306*4882a593Smuzhiyun ({ int __sio(var)(ok) = 0; \ 307*4882a593Smuzhiyun typeof(__a) __sio(var)(_a) = (__a); \ 308*4882a593Smuzhiyun typeof(__b) __sio(var)(_b) = (__b); \ 309*4882a593Smuzhiyun typeof(_ptr) __sio(var)(p) = (_ptr); \ 310*4882a593Smuzhiyun if (__sio(m)(assert)(__sio(m)(type_enforce)(__sio(var)(_a), \ 311*4882a593Smuzhiyun __sio(var)(_b)))) { \ 312*4882a593Smuzhiyun if (__sio(m)(umax)(__sio(var)(_a)) <= ((typeof(__sio(var)(_a)))0)) { \ 313*4882a593Smuzhiyun __sio(var)(ok) = safe_smod(__sio(var)(p), \ 314*4882a593Smuzhiyun __sio(var)(_a), \ 315*4882a593Smuzhiyun __sio(var)(_b)); \ 316*4882a593Smuzhiyun } else { \ 317*4882a593Smuzhiyun __sio(var)(ok) = safe_umod(__sio(var)(p), \ 318*4882a593Smuzhiyun __sio(var)(_a), \ 319*4882a593Smuzhiyun __sio(var)(_b)); \ 320*4882a593Smuzhiyun } \ 321*4882a593Smuzhiyun } \ 322*4882a593Smuzhiyun __sio(var)(ok); }) 323*4882a593Smuzhiyun 324*4882a593Smuzhiyun #define safe_mod3(_ptr, _A, _B, _C) \ 325*4882a593Smuzhiyun ({ typeof(_A) __sio(var)(a) = (_A); \ 326*4882a593Smuzhiyun typeof(_B) __sio(var)(b) = (_B); \ 327*4882a593Smuzhiyun typeof(_C) __sio(var)(c) = (_C); \ 328*4882a593Smuzhiyun typeof(_A) __sio(var)(r) = 0; \ 329*4882a593Smuzhiyun (safe_mod(&(__sio(var)(r)), __sio(var)(a), __sio(var)(b)) && \ 330*4882a593Smuzhiyun safe_mod((_ptr), __sio(var)(r), __sio(var)(c))); }) 331*4882a593Smuzhiyun 332*4882a593Smuzhiyun #define safe_mod4(_ptr, _A, _B, _C, _D) \ 333*4882a593Smuzhiyun ({ typeof(_A) __sio(var)(a) = (_A); \ 334*4882a593Smuzhiyun typeof(_B) __sio(var)(b) = (_B); \ 335*4882a593Smuzhiyun typeof(_C) __sio(var)(c) = (_C); \ 336*4882a593Smuzhiyun typeof(_D) __sio(var)(d) = (_D); \ 337*4882a593Smuzhiyun typeof(_A) __sio(var)(r) = 0; \ 338*4882a593Smuzhiyun (safe_mod(&(__sio(var)(r)), __sio(var)(a), __sio(var)(b)) && \ 339*4882a593Smuzhiyun safe_mod(&(__sio(var)(r)), __sio(var)(r), __sio(var)(c)) && \ 340*4882a593Smuzhiyun safe_mod((_ptr), __sio(var)(r), (__sio(var)(d)))); }) 341*4882a593Smuzhiyun 342*4882a593Smuzhiyun #define safe_mod5(_ptr, _A, _B, _C, _D, _E) \ 343*4882a593Smuzhiyun ({ typeof(_A) __sio(var)(a) = (_A); \ 344*4882a593Smuzhiyun typeof(_B) __sio(var)(b) = (_B); \ 345*4882a593Smuzhiyun typeof(_C) __sio(var)(c) = (_C), \ 346*4882a593Smuzhiyun typeof(_D) __sio(var)(d) = (_D); \ 347*4882a593Smuzhiyun typeof(_E) __sio(var)(e) = (_E); \ 348*4882a593Smuzhiyun typeof(_A) __sio(var)(r) = 0; \ 349*4882a593Smuzhiyun (safe_mod(&(__sio(var)(r)), __sio(var)(a), __sio(var)(b)) && \ 350*4882a593Smuzhiyun safe_mod(&(__sio(var)(r)), __sio(var)(r), __sio(var)(c)) && \ 351*4882a593Smuzhiyun safe_mod(&(__sio(var)(r)), __sio(var)(r), __sio(var)(d)) && \ 352*4882a593Smuzhiyun safe_mod((_ptr), __sio(var)(r), __sio(var)(e))); }) 353*4882a593Smuzhiyun 354*4882a593Smuzhiyun /*** Safe integer operation implementation macros ***/ 355*4882a593Smuzhiyun 356*4882a593Smuzhiyun #define safe_uadd(_ptr, _a, _b) \ 357*4882a593Smuzhiyun ({ int __sio(var)(ok) = 0; \ 358*4882a593Smuzhiyun if ((typeof(_a))(_b) <= (typeof(_a))(__sio(m)(umax)(_a) - (_a))) { \ 359*4882a593Smuzhiyun if ((_ptr)) { *((typeof(_a)*)(_ptr)) = (_a) + (_b); } \ 360*4882a593Smuzhiyun __sio(var)(ok) = 1; \ 361*4882a593Smuzhiyun } __sio(var)(ok); }) 362*4882a593Smuzhiyun 363*4882a593Smuzhiyun #define safe_sadd(_ptr, _a, _b) \ 364*4882a593Smuzhiyun ({ int __sio(var)(ok) = 1; \ 365*4882a593Smuzhiyun if (((_b) > (typeof(_a))0) && ((_a) > (typeof(_a))0)) { /*>0*/ \ 366*4882a593Smuzhiyun if ((_a) > (typeof(_a))(__sio(m)(smax)(_a) - (_b))) __sio(var)(ok) = 0; \ 367*4882a593Smuzhiyun } else if (!((_b) > (typeof(_a))0) && !((_a) > (typeof(_a))0)) { /*<0*/ \ 368*4882a593Smuzhiyun if ((_a) < (typeof(_a))(__sio(m)(smin)(_a) - (_b))) __sio(var)(ok) = 0; \ 369*4882a593Smuzhiyun } \ 370*4882a593Smuzhiyun if (__sio(var)(ok) && (_ptr)) { *((typeof(_a)*)(_ptr)) = (_a) + (_b); } \ 371*4882a593Smuzhiyun __sio(var)(ok); }) 372*4882a593Smuzhiyun 373*4882a593Smuzhiyun #define safe_usub(_ptr, _a, _b) \ 374*4882a593Smuzhiyun ({ int __sio(var)(ok) = 0; \ 375*4882a593Smuzhiyun if ((_a) >= (_b)) { \ 376*4882a593Smuzhiyun if ((_ptr)) { *((typeof(_a)*)(_ptr)) = (_a) - (_b); } \ 377*4882a593Smuzhiyun __sio(var)(ok) = 1; \ 378*4882a593Smuzhiyun } \ 379*4882a593Smuzhiyun __sio(var)(ok); }) 380*4882a593Smuzhiyun 381*4882a593Smuzhiyun #define safe_ssub(_ptr, _a, _b) \ 382*4882a593Smuzhiyun ({ int __sio(var)(ok) = 0; \ 383*4882a593Smuzhiyun if (!((_b) <= 0 && (_a) > (__sio(m)(smax)(_a) + (_b))) && \ 384*4882a593Smuzhiyun !((_b) > 0 && (_a) < (__sio(m)(smin)(_a) + (_b)))) { \ 385*4882a593Smuzhiyun __sio(var)(ok) = 1; \ 386*4882a593Smuzhiyun if ((_ptr)) { *((typeof(_a)*)(_ptr)) = (_a) - (_b); } \ 387*4882a593Smuzhiyun } \ 388*4882a593Smuzhiyun __sio(var)(ok); }) 389*4882a593Smuzhiyun 390*4882a593Smuzhiyun #define safe_umul(_ptr, _a, _b) \ 391*4882a593Smuzhiyun ({ int __sio(var)(ok) = 0; \ 392*4882a593Smuzhiyun if (!(_b) || (_a) <= (__sio(m)(umax)(_a) / (_b))) { \ 393*4882a593Smuzhiyun __sio(var)(ok) = 1; \ 394*4882a593Smuzhiyun if ((_ptr)) { *((typeof(_a)*)(_ptr)) = (_a) * (_b); } \ 395*4882a593Smuzhiyun } \ 396*4882a593Smuzhiyun __sio(var)(ok); }) 397*4882a593Smuzhiyun 398*4882a593Smuzhiyun #define safe_smul(_ptr, _a, _b) \ 399*4882a593Smuzhiyun ({ int __sio(var)(ok) = 1; \ 400*4882a593Smuzhiyun if ((_a) > 0) { /* a is positive */ \ 401*4882a593Smuzhiyun if ((_b) > 0) { /* b and a are positive */ \ 402*4882a593Smuzhiyun if ((_a) > (__sio(m)(smax)(_a) / (_b))) { \ 403*4882a593Smuzhiyun __sio(var)(ok) = 0; \ 404*4882a593Smuzhiyun } \ 405*4882a593Smuzhiyun } /* end if a and b are positive */ \ 406*4882a593Smuzhiyun else { /* a positive, b non-positive */ \ 407*4882a593Smuzhiyun if ((_b) < (__sio(m)(smin)(_a) / (_a))) { \ 408*4882a593Smuzhiyun __sio(var)(ok) = 0; \ 409*4882a593Smuzhiyun } \ 410*4882a593Smuzhiyun } /* a positive, b non-positive */ \ 411*4882a593Smuzhiyun } /* end if a is positive */ \ 412*4882a593Smuzhiyun else { /* a is non-positive */ \ 413*4882a593Smuzhiyun if ((_b) > 0) { /* a is non-positive, b is positive */ \ 414*4882a593Smuzhiyun if ((_a) < (__sio(m)(smin)(_a) / (_b))) { \ 415*4882a593Smuzhiyun __sio(var)(ok) = 0; \ 416*4882a593Smuzhiyun } \ 417*4882a593Smuzhiyun } /* end if a is non-positive, b is positive */ \ 418*4882a593Smuzhiyun else { /* a and b are non-positive */ \ 419*4882a593Smuzhiyun if( ((_a) != 0) && ((_b) < (__sio(m)(smax)(_a) / (_a)))) { \ 420*4882a593Smuzhiyun __sio(var)(ok) = 0; \ 421*4882a593Smuzhiyun } \ 422*4882a593Smuzhiyun } /* end if a and b are non-positive */ \ 423*4882a593Smuzhiyun } /* end if a is non-positive */ \ 424*4882a593Smuzhiyun if (__sio(var)(ok) && (_ptr)) { *((typeof(_a)*)(_ptr)) = (_a) * (_b); } \ 425*4882a593Smuzhiyun __sio(var)(ok); }) 426*4882a593Smuzhiyun 427*4882a593Smuzhiyun /* div-by-zero is the only thing addressed */ 428*4882a593Smuzhiyun #define safe_udiv(_ptr, _a, _b) \ 429*4882a593Smuzhiyun ({ int __sio(var)(ok) = 0; \ 430*4882a593Smuzhiyun if ((_b) != 0) { \ 431*4882a593Smuzhiyun if ((_ptr)) { *((typeof(_a)*)(_ptr)) = (_a) / (_b); } \ 432*4882a593Smuzhiyun __sio(var)(ok) = 1; \ 433*4882a593Smuzhiyun } \ 434*4882a593Smuzhiyun __sio(var)(ok); }) 435*4882a593Smuzhiyun 436*4882a593Smuzhiyun /* Addreses div by zero and smin -1 */ 437*4882a593Smuzhiyun #define safe_sdiv(_ptr, _a, _b) \ 438*4882a593Smuzhiyun ({ int __sio(var)(ok) = 0; \ 439*4882a593Smuzhiyun if ((_b) != 0 && \ 440*4882a593Smuzhiyun (((_a) != __sio(m)(smin)(_a)) || ((_b) != (typeof(_b))-1))) { \ 441*4882a593Smuzhiyun if ((_ptr)) { *((typeof(_a)*)(_ptr)) = (_a) / (_b); } \ 442*4882a593Smuzhiyun __sio(var)(ok) = 1; \ 443*4882a593Smuzhiyun } \ 444*4882a593Smuzhiyun __sio(var)(ok); }) 445*4882a593Smuzhiyun 446*4882a593Smuzhiyun #define safe_umod(_ptr, _a, _b) \ 447*4882a593Smuzhiyun ({ int __sio(var)(ok) = 0; \ 448*4882a593Smuzhiyun if ((_b) != 0) { \ 449*4882a593Smuzhiyun if ((_ptr)) { *((typeof(_a)*)(_ptr)) = (_a) % (_b); } \ 450*4882a593Smuzhiyun __sio(var)(ok) = 1; \ 451*4882a593Smuzhiyun } \ 452*4882a593Smuzhiyun __sio(var)(ok); }) 453*4882a593Smuzhiyun 454*4882a593Smuzhiyun #define safe_smod(_ptr, _a, _b) \ 455*4882a593Smuzhiyun ({ int __sio(var)(ok) = 0; \ 456*4882a593Smuzhiyun if ((_b) != 0 && \ 457*4882a593Smuzhiyun (((_a) != __sio(m)(smin)(_a)) || ((_b) != (typeof(_b))-1))) { \ 458*4882a593Smuzhiyun if ((_ptr)) { *((typeof(_a)*)(_ptr)) = (_a) % (_b); } \ 459*4882a593Smuzhiyun __sio(var)(ok) = 1; \ 460*4882a593Smuzhiyun } \ 461*4882a593Smuzhiyun __sio(var)(ok); }) 462*4882a593Smuzhiyun 463*4882a593Smuzhiyun #if SAFE_IOP_COMPAT 464*4882a593Smuzhiyun /* These are used for testing for easy type enforcement */ 465*4882a593Smuzhiyun #include <sys/types.h> 466*4882a593Smuzhiyun #include <limits.h> 467*4882a593Smuzhiyun 468*4882a593Smuzhiyun #ifndef SAFE_IOP_INLINE 469*4882a593Smuzhiyun # if defined(__GNUC__) && (__GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR__ > 0) 470*4882a593Smuzhiyun # define SAFE_IOP_INLINE __attribute__((always_inline)) static inline 471*4882a593Smuzhiyun # else 472*4882a593Smuzhiyun # define SAFE_IOP_INLINE static inline 473*4882a593Smuzhiyun # endif 474*4882a593Smuzhiyun #endif 475*4882a593Smuzhiyun 476*4882a593Smuzhiyun #define MAKE_UADD(_prefix, _bits, _type, _max) \ 477*4882a593Smuzhiyun SAFE_IOP_INLINE \ 478*4882a593Smuzhiyun int safe_add##_prefix##_bits (_type *result, _type value, _type a) { \ 479*4882a593Smuzhiyun return safe_uadd(result, value, a); \ 480*4882a593Smuzhiyun } 481*4882a593Smuzhiyun 482*4882a593Smuzhiyun #define MAKE_SADD(_prefix, _bits, _type, _max) \ 483*4882a593Smuzhiyun SAFE_IOP_INLINE \ 484*4882a593Smuzhiyun int safe_add##_prefix##_bits(_type *result, _type value, _type a) { \ 485*4882a593Smuzhiyun return safe_sadd(result, value, a); \ 486*4882a593Smuzhiyun } 487*4882a593Smuzhiyun 488*4882a593Smuzhiyun #define MAKE_USUB(_prefix, _bits, _type) \ 489*4882a593Smuzhiyun SAFE_IOP_INLINE \ 490*4882a593Smuzhiyun int safe_sub##_prefix##_bits(_type *result, _type value, _type a) { \ 491*4882a593Smuzhiyun return safe_usub(result, value, a); \ 492*4882a593Smuzhiyun } 493*4882a593Smuzhiyun 494*4882a593Smuzhiyun #define MAKE_SSUB(_prefix, _bits, _type, _min, _max) \ 495*4882a593Smuzhiyun SAFE_IOP_INLINE \ 496*4882a593Smuzhiyun int safe_sub##_prefix##_bits(_type *result, _type value, _type a) { \ 497*4882a593Smuzhiyun return safe_ssub(result, value, a); \ 498*4882a593Smuzhiyun } 499*4882a593Smuzhiyun 500*4882a593Smuzhiyun #define MAKE_UMUL(_prefix, _bits, _type, _max) \ 501*4882a593Smuzhiyun SAFE_IOP_INLINE \ 502*4882a593Smuzhiyun int safe_mul##_prefix##_bits(_type *result, _type value, _type a) { \ 503*4882a593Smuzhiyun return safe_umul(result, value, a); \ 504*4882a593Smuzhiyun } 505*4882a593Smuzhiyun 506*4882a593Smuzhiyun 507*4882a593Smuzhiyun #define MAKE_SMUL(_prefix, _bits, _type, _max, _min) \ 508*4882a593Smuzhiyun SAFE_IOP_INLINE \ 509*4882a593Smuzhiyun int safe_mul##_prefix##_bits(_type *result, _type value, _type a) { \ 510*4882a593Smuzhiyun return safe_smul(result, value, a); \ 511*4882a593Smuzhiyun } 512*4882a593Smuzhiyun 513*4882a593Smuzhiyun #define MAKE_UDIV(_prefix, _bits, _type) \ 514*4882a593Smuzhiyun SAFE_IOP_INLINE \ 515*4882a593Smuzhiyun int safe_div##_prefix##_bits(_type *result, _type value, _type a) { \ 516*4882a593Smuzhiyun return safe_udiv(result, value, a); \ 517*4882a593Smuzhiyun } 518*4882a593Smuzhiyun 519*4882a593Smuzhiyun #define MAKE_SDIV(_prefix, _bits, _type, _min) \ 520*4882a593Smuzhiyun SAFE_IOP_INLINE \ 521*4882a593Smuzhiyun int safe_div##_prefix##_bits(_type *result, _type value, _type a) { \ 522*4882a593Smuzhiyun return safe_sdiv(result, value, a); \ 523*4882a593Smuzhiyun } 524*4882a593Smuzhiyun 525*4882a593Smuzhiyun #define MAKE_UMOD(_prefix, _bits, _type) \ 526*4882a593Smuzhiyun SAFE_IOP_INLINE \ 527*4882a593Smuzhiyun int safe_mod##_prefix##_bits(_type *result, _type value, _type a) { \ 528*4882a593Smuzhiyun return safe_umod(result, value, a); \ 529*4882a593Smuzhiyun } 530*4882a593Smuzhiyun 531*4882a593Smuzhiyun #define MAKE_SMOD(_prefix, _bits, _type, _min) \ 532*4882a593Smuzhiyun SAFE_IOP_INLINE \ 533*4882a593Smuzhiyun int safe_mod##_prefix##_bits(_type *result, _type value, _type a) { \ 534*4882a593Smuzhiyun return safe_smod(result, value, a); \ 535*4882a593Smuzhiyun } 536*4882a593Smuzhiyun 537*4882a593Smuzhiyun /* __LP64__ is given by GCC. Without more work, this is bound to GCC. */ 538*4882a593Smuzhiyun #if __LP64__ == 1 || __SIZEOF_LONG__ > __SIZEOF_INT__ 539*4882a593Smuzhiyun # define SAFE_INT64_MAX 0x7fffffffffffffffL 540*4882a593Smuzhiyun # define SAFE_UINT64_MAX 0xffffffffffffffffUL 541*4882a593Smuzhiyun # define SAFE_INT64_MIN (-SAFE_INT64_MAX - 1L) 542*4882a593Smuzhiyun #elif __SIZEOF_LONG__ == __SIZEOF_INT__ 543*4882a593Smuzhiyun # define SAFE_INT64_MAX 0x7fffffffffffffffLL 544*4882a593Smuzhiyun # define SAFE_UINT64_MAX 0xffffffffffffffffULL 545*4882a593Smuzhiyun # define SAFE_INT64_MIN (-SAFE_INT64_MAX - 1LL) 546*4882a593Smuzhiyun #else 547*4882a593Smuzhiyun # warning "64-bit support disabled" 548*4882a593Smuzhiyun # define SAFE_IOP_NO_64 1 549*4882a593Smuzhiyun #endif 550*4882a593Smuzhiyun 551*4882a593Smuzhiyun /* Assumes SSIZE_MAX */ 552*4882a593Smuzhiyun #ifndef SSIZE_MIN 553*4882a593Smuzhiyun # if SSIZE_MAX == LONG_MAX 554*4882a593Smuzhiyun # define SSIZE_MIN LONG_MIN 555*4882a593Smuzhiyun # elif SSIZE_MAX == LONG_LONG_MAX 556*4882a593Smuzhiyun # define SSIZE_MIN LONG_LONG_MIN 557*4882a593Smuzhiyun # else 558*4882a593Smuzhiyun # error "SSIZE_MIN is not defined and could not be guessed" 559*4882a593Smuzhiyun # endif 560*4882a593Smuzhiyun #endif 561*4882a593Smuzhiyun 562*4882a593Smuzhiyun 563*4882a593Smuzhiyun 564*4882a593Smuzhiyun #ifndef SAFE_IOP_NO_64 565*4882a593Smuzhiyun MAKE_UADD(u, 64, u_int64_t, SAFE_UINT64_MAX) 566*4882a593Smuzhiyun #endif 567*4882a593Smuzhiyun MAKE_UADD(, szt, size_t, SIZE_MAX) 568*4882a593Smuzhiyun MAKE_UADD(u, 32, u_int32_t, UINT_MAX) 569*4882a593Smuzhiyun MAKE_UADD(u, 16, u_int16_t, USHRT_MAX) 570*4882a593Smuzhiyun MAKE_UADD(u, 8, u_int8_t, UCHAR_MAX) 571*4882a593Smuzhiyun 572*4882a593Smuzhiyun #ifndef SAFE_IOP_NO_64 573*4882a593Smuzhiyun MAKE_SADD(s, 64, int64_t, SAFE_INT64_MAX) 574*4882a593Smuzhiyun #endif 575*4882a593Smuzhiyun MAKE_SADD(s, szt, ssize_t, SSIZE_MAX) 576*4882a593Smuzhiyun MAKE_SADD(s, 32, int32_t, INT_MAX) 577*4882a593Smuzhiyun MAKE_SADD(s, 16, int16_t, SHRT_MAX) 578*4882a593Smuzhiyun MAKE_SADD(s, 8, int8_t, SCHAR_MAX) 579*4882a593Smuzhiyun 580*4882a593Smuzhiyun #ifndef SAFE_IOP_NO_64 581*4882a593Smuzhiyun MAKE_USUB(u, 64, u_int64_t) 582*4882a593Smuzhiyun #endif 583*4882a593Smuzhiyun MAKE_USUB(, szt, size_t) 584*4882a593Smuzhiyun MAKE_USUB(u, 32, u_int32_t) 585*4882a593Smuzhiyun MAKE_USUB(u, 16, u_int16_t) 586*4882a593Smuzhiyun MAKE_USUB(u, 8, u_int8_t) 587*4882a593Smuzhiyun 588*4882a593Smuzhiyun #ifndef SAFE_IOP_NO_64 589*4882a593Smuzhiyun MAKE_SSUB(s, 64, int64_t, SAFE_INT64_MIN, SAFE_INT64_MAX) 590*4882a593Smuzhiyun #endif 591*4882a593Smuzhiyun MAKE_SSUB(s, szt, ssize_t, SSIZE_MIN, SSIZE_MAX) 592*4882a593Smuzhiyun MAKE_SSUB(s, 32, int32_t, INT_MIN, INT_MAX) 593*4882a593Smuzhiyun MAKE_SSUB(s, 16, int16_t, SHRT_MIN, SHRT_MAX) 594*4882a593Smuzhiyun MAKE_SSUB(s, 8, int8_t, SCHAR_MIN, SCHAR_MAX) 595*4882a593Smuzhiyun 596*4882a593Smuzhiyun 597*4882a593Smuzhiyun #ifndef SAFE_IOP_NO_64 598*4882a593Smuzhiyun MAKE_UMUL(u, 64, u_int64_t, SAFE_UINT64_MAX) 599*4882a593Smuzhiyun #endif 600*4882a593Smuzhiyun MAKE_UMUL(, szt, size_t, SIZE_MAX) 601*4882a593Smuzhiyun MAKE_UMUL(u, 32, u_int32_t, UINT_MAX) 602*4882a593Smuzhiyun MAKE_UMUL(u, 16, u_int16_t, USHRT_MAX) 603*4882a593Smuzhiyun MAKE_UMUL(u, 8, u_int8_t, UCHAR_MAX) 604*4882a593Smuzhiyun 605*4882a593Smuzhiyun #ifndef SAFE_IOP_NO_64 606*4882a593Smuzhiyun MAKE_SMUL(s, 64, int64_t, SAFE_INT64_MAX, SAFE_INT64_MIN) 607*4882a593Smuzhiyun #endif 608*4882a593Smuzhiyun MAKE_SMUL(s, szt, ssize_t, SSIZE_MAX, SSIZE_MIN) 609*4882a593Smuzhiyun MAKE_SMUL(s, 32, int32_t, INT_MAX, INT_MIN) 610*4882a593Smuzhiyun MAKE_SMUL(s, 16, int16_t, SHRT_MAX, SHRT_MIN) 611*4882a593Smuzhiyun MAKE_SMUL(s, 8, int8_t, SCHAR_MAX, SCHAR_MIN) 612*4882a593Smuzhiyun 613*4882a593Smuzhiyun 614*4882a593Smuzhiyun #ifndef SAFE_IOP_NO_64 615*4882a593Smuzhiyun MAKE_UDIV(u, 64, u_int64_t) 616*4882a593Smuzhiyun #endif 617*4882a593Smuzhiyun MAKE_UDIV(, szt, size_t) 618*4882a593Smuzhiyun MAKE_UDIV(u, 32, u_int32_t) 619*4882a593Smuzhiyun MAKE_UDIV(u, 16, u_int16_t) 620*4882a593Smuzhiyun MAKE_UDIV(u, 8, u_int8_t) 621*4882a593Smuzhiyun 622*4882a593Smuzhiyun #ifndef SAFE_IOP_NO_64 623*4882a593Smuzhiyun MAKE_SDIV(s, 64, int64_t, SAFE_INT64_MIN) 624*4882a593Smuzhiyun #endif 625*4882a593Smuzhiyun MAKE_SDIV(s, szt, ssize_t, SSIZE_MIN) 626*4882a593Smuzhiyun MAKE_SDIV(s, 32, int32_t, INT_MIN) 627*4882a593Smuzhiyun MAKE_SDIV(s, 16, int16_t, SHRT_MIN) 628*4882a593Smuzhiyun MAKE_SDIV(s, 8, int8_t, SCHAR_MIN) 629*4882a593Smuzhiyun 630*4882a593Smuzhiyun 631*4882a593Smuzhiyun #ifndef SAFE_IOP_NO_64 632*4882a593Smuzhiyun MAKE_UMOD(u, 64, u_int64_t) 633*4882a593Smuzhiyun #endif 634*4882a593Smuzhiyun MAKE_UMOD(, szt, size_t) 635*4882a593Smuzhiyun MAKE_UMOD(u, 32, u_int32_t) 636*4882a593Smuzhiyun MAKE_UMOD(u, 16, u_int16_t) 637*4882a593Smuzhiyun MAKE_UMOD(u, 8, u_int8_t) 638*4882a593Smuzhiyun 639*4882a593Smuzhiyun #ifndef SAFE_IOP_NO_64 640*4882a593Smuzhiyun MAKE_SMOD(s, 64, int64_t, SAFE_INT64_MIN) 641*4882a593Smuzhiyun #endif 642*4882a593Smuzhiyun MAKE_SMOD(s, szt, ssize_t, SSIZE_MIN) 643*4882a593Smuzhiyun MAKE_SMOD(s, 32, int32_t, INT_MIN) 644*4882a593Smuzhiyun MAKE_SMOD(s, 16, int16_t, SHRT_MIN) 645*4882a593Smuzhiyun MAKE_SMOD(s, 8, int8_t, SCHAR_MIN) 646*4882a593Smuzhiyun 647*4882a593Smuzhiyun /* Cleanup the macro spam */ 648*4882a593Smuzhiyun #undef MAKE_SMUL 649*4882a593Smuzhiyun #undef MAKE_UMUL 650*4882a593Smuzhiyun #undef MAKE_SSUB 651*4882a593Smuzhiyun #undef MAKE_USUB 652*4882a593Smuzhiyun #undef MAKE_SADD 653*4882a593Smuzhiyun #undef MAKE_UADD 654*4882a593Smuzhiyun #undef MAKE_UDIV 655*4882a593Smuzhiyun #undef MAKE_SDIV 656*4882a593Smuzhiyun #undef MAKE_UMOD 657*4882a593Smuzhiyun #undef MAKE_SMOD 658*4882a593Smuzhiyun 659*4882a593Smuzhiyun #endif /* SAFE_IOP_COMPAT */ 660*4882a593Smuzhiyun 661*4882a593Smuzhiyun 662*4882a593Smuzhiyun 663*4882a593Smuzhiyun /* safe_iopf 664*4882a593Smuzhiyun * 665*4882a593Smuzhiyun * Takes in a character array which specifies the operations 666*4882a593Smuzhiyun * to perform on a given value. The value will be assumed to be 667*4882a593Smuzhiyun * of the type specified for each operation. 668*4882a593Smuzhiyun * 669*4882a593Smuzhiyun * Currently accepted format syntax is: 670*4882a593Smuzhiyun * [type_marker]operation... 671*4882a593Smuzhiyun * The type marker may be any of the following: 672*4882a593Smuzhiyun * - s32 for signed int32 673*4882a593Smuzhiyun * - u32 for unsigned int32 674*4882a593Smuzhiyun * If no type_marker is specified, it is assumed to be s32. 675*4882a593Smuzhiyun * 676*4882a593Smuzhiyun * Currently, this only performs correctly with 32-bit integers. 677*4882a593Smuzhiyun * 678*4882a593Smuzhiyun * The operation must be one of the following: 679*4882a593Smuzhiyun * - * -- multiplication 680*4882a593Smuzhiyun * - / -- division 681*4882a593Smuzhiyun * - - -- subtraction 682*4882a593Smuzhiyun * - + -- addition 683*4882a593Smuzhiyun * - % -- modulo (remainder) 684*4882a593Smuzhiyun * 685*4882a593Smuzhiyun * Whitespace will be ignored. 686*4882a593Smuzhiyun * 687*4882a593Smuzhiyun * Args: 688*4882a593Smuzhiyun * - pointer to the final result (this must be at least the size of int32) 689*4882a593Smuzhiyun * - array of format characters 690*4882a593Smuzhiyun * - all remaining arguments are derived from the format 691*4882a593Smuzhiyun * Output: 692*4882a593Smuzhiyun * - Returns 1 on success leaving the result in value 693*4882a593Smuzhiyun * - Returns 0 on failure leaving the contents of value *unknown* 694*4882a593Smuzhiyun */ 695*4882a593Smuzhiyun 696*4882a593Smuzhiyun int safe_iopf(void *result, const char *const fmt, ...); 697*4882a593Smuzhiyun 698*4882a593Smuzhiyun 699*4882a593Smuzhiyun #endif /* _SAFE_IOP_H */ 700