Home | History | Annotate | Download | only in include
      1 /* safe_iop
      2  * License:: released in to the public domain
      3  * Author:: Will Drewry <redpig (at) dataspill.org>
      4  * Copyright 2007,2008 redpig (at) 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 (at) 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