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