The Android Open Source Project | e154e42 | 2009-03-03 19:30:35 -0800 | [diff] [blame] | 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 */ |