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 62typedef 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 567MAKE_UADD(,szt, size_t, SIZE_MAX) 568MAKE_UADD(u, 32, u_int32_t, UINT_MAX) 569MAKE_UADD(u, 16, u_int16_t, USHRT_MAX) 570MAKE_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 575MAKE_SADD(s, szt, ssize_t, SSIZE_MAX) 576MAKE_SADD(s, 32, int32_t, INT_MAX) 577MAKE_SADD(s, 16, int16_t, SHRT_MAX) 578MAKE_SADD(s, 8, int8_t, SCHAR_MAX) 579 580#ifndef SAFE_IOP_NO_64 581 MAKE_USUB(u, 64, u_int64_t) 582#endif 583MAKE_USUB(, szt, size_t) 584MAKE_USUB(u, 32, u_int32_t) 585MAKE_USUB(u, 16, u_int16_t) 586MAKE_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 591MAKE_SSUB(s, szt, ssize_t, SSIZE_MIN, SSIZE_MAX) 592MAKE_SSUB(s, 32, int32_t, INT_MIN, INT_MAX) 593MAKE_SSUB(s, 16, int16_t, SHRT_MIN, SHRT_MAX) 594MAKE_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 600MAKE_UMUL(, szt, size_t, SIZE_MAX) 601MAKE_UMUL(u, 32, u_int32_t, UINT_MAX) 602MAKE_UMUL(u, 16, u_int16_t, USHRT_MAX) 603MAKE_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 608MAKE_SMUL(s, szt, ssize_t, SSIZE_MAX, SSIZE_MIN) 609MAKE_SMUL(s, 32, int32_t, INT_MAX, INT_MIN) 610MAKE_SMUL(s, 16, int16_t, SHRT_MAX, SHRT_MIN) 611MAKE_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 617MAKE_UDIV(, szt, size_t) 618MAKE_UDIV(u, 32, u_int32_t) 619MAKE_UDIV(u, 16, u_int16_t) 620MAKE_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 625MAKE_SDIV(s, szt, ssize_t, SSIZE_MIN) 626MAKE_SDIV(s, 32, int32_t, INT_MIN) 627MAKE_SDIV(s, 16, int16_t, SHRT_MIN) 628MAKE_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 634MAKE_UMOD(, szt, size_t) 635MAKE_UMOD(u, 32, u_int32_t) 636MAKE_UMOD(u, 16, u_int16_t) 637MAKE_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 642MAKE_SMOD(s, szt, ssize_t, SSIZE_MIN) 643MAKE_SMOD(s, 32, int32_t, INT_MIN) 644MAKE_SMOD(s, 16, int16_t, SHRT_MIN) 645MAKE_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 696int safe_iopf(void *result, const char *const fmt, ...); 697 698 699#endif /* _SAFE_IOP_H */ 700