tech-userlevel archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

detecting integer over/underflow



Hello,

Currently it is not easy to detect if a value will fit into a type
so I wrote the following macros to simplify this.

Basically we have:

        __overflow(type, value)

That returns false if value fits in type, and true if not. If anyone knows
of a simpler way of doing this, I am all ears :-)

I am planning to use this macro inside _DIAGASSERT() in libc where we
are converting from long -> int on _LP64 to detect overflow. This happens
a lot when size_t, off_t, ptrdiff_t is involved. lint(1) warns when this
happens, and so I would like to add this _DIAGASSERT() before I add a cast.
Under normal operation nothing changes, i.e. the compiler ends up generating
no different code than before, since the _DIAGASSERT() turns into nothing.
When _DIAGNOSTIC() is turned on, it will assert when an overflow occurs.
I wanted to do this to provide documentation where there is a possible
overflow before the cast so that the cast does not get ignored.

size_t x;
int y;

Old:

        y += x;

New:

        _DIAGASSERT(int, y + x);
        y += (int)x;

christos

Index: cdefs.h
===================================================================
RCS file: /cvsroot/src/sys/sys/cdefs.h,v
retrieving revision 1.92
diff -u -p -u -r1.92 cdefs.h
--- cdefs.h     22 Feb 2012 17:52:58 -0000      1.92
+++ cdefs.h     4 Mar 2012 19:18:27 -0000
@@ -530,4 +530,27 @@
 #define __CAST(__dt, __st)     ((__dt)(__st))
 #endif
 
+#define __type_mask(t) (/*LINTED*/sizeof(t) < sizeof(intmax_t) ? \
+    (~((1ULL << (sizeof(t) * NBBY)) - 1)) : 0ULL)
+
+#define __type_min_s(t) ((t)((1ULL << (sizeof(t) * NBBY - 1))))
+#define __type_max_s(t) ((t)~((1ULL << (sizeof(t) * NBBY - 1))))
+#define __type_min_u(t) ((t)0ULL)
+#define __type_max_u(t) ((t)~0ULL)
+#define __type_is_signed(t) (/*LINTED*/__type_min_s(t) + (t)1 < (t)1)
+#define __type_min(t) (__type_is_signed(t) ? __type_min_s(t) : __type_min_u(t))
+#define __type_max(t) (__type_is_signed(t) ? __type_max_s(t) : __type_max_u(t))
+
+static __inline int __negative(double x) { return x < 0; }
+
+#define __overflow_u(t, a) (/*LINTED*/sizeof(t) < sizeof(intmax_t) ? \
+    (((a) & __type_mask(t)) != 0) : __negative(a))
+
+#define __overflow_s(t, a) (/*LINTED*/__negative(a) ? \
+    ((intmax_t)(a) < (intmax_t)__type_min_s(t)) : \
+    ((intmax_t)(a) > (intmax_t)__type_max_s(t)))
+
+#define __overflow(t, a) (__type_is_signed(t) ? \
+    __overflow_s(t, a) : __overflow_u(t, a))
+
 #endif /* !_SYS_CDEFS_H_ */


Home | Main Index | Thread Index | Old Index