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