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