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