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