I am adding some integer overflow checking to GNU Emacs, and RMS suggested that I make it a gnulib module, which sounds like a good suggestion, so here's a proposed module.
--- intoverflow: new module This is being put in for Emacs; I think coreutils can use it too. See <http://debbugs.gnu.org/cgi/bugreport.cgi?bug=8545#123>. * lib/intoverflow.h, modules/intoverflow: New files. diff --git a/lib/intoverflow.h b/lib/intoverflow.h new file mode 100644 index 0000000..af00855 --- /dev/null +++ b/lib/intoverflow.h @@ -0,0 +1,88 @@ +/* Check for integer overflow. + + Copyright (C) 2011 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +/* Written by Paul Eggert. */ + +#ifndef _GL_INTOVERFLOW_H +#define _GL_INTOVERFLOW_H + +/* These macros return 1 if the corresponding C operators might + not yield numerically correct answers due to arithmetic overflow. + They do not check for all possible numerical problems or undefined + behavior; for example, they do not check for division by zero. Nor + is the behavior necessarily undefined if they return 1; for example, + they return 1 when unsigned arithmetic overflows, even though the + behavior is well-defined to wrap around. + + These macros may evaluate their arguments multiple times, so the + arguments should not have side effects. The arithmetic macros + assume that arguments are of the same integer type, and that the + type has minimum value MIN and maximum MAX. Unsigned types should + use a zero MIN. + + These macros are tuned for constant MIN and MAX. For commutative + operations such as A + B, they are also tuned for constant B. */ + +/* Return 1 if A + B would overflow. */ +#define ADD_OVERFLOW(a, b, min, max) \ + ((b) < 0 \ + ? (a) < (min) - (b) \ + : (max) - (b) < (a)) + +/* Return 1 if A - B would overflow. */ +#define SUBTRACT_OVERFLOW(a, b, min, max) \ + ((b) < 0 \ + ? (max) + (b) < (a) \ + : (a) < (min) + (b)) + +/* Return 1 if - A would overflow. */ +#define NEGATE_OVERFLOW(a, min, max) \ + ((min) < 0 \ + ? (a) < - (max) \ + : 0 < (a)) + +/* Return 1 if A * B would overflow. */ +#define MULTIPLY_OVERFLOW(a, b, min, max) \ + ((b) < 0 \ + ? ((a) < 0 \ + ? (a) < (max) / (b) \ + : (b) < -1 && (min) / (b) < (a)) \ + : (0 < (b) \ + && ((a) < 0 \ + ? (a) < (min) / (b) \ + : (max) / (b) < (a)))) + +/* Return 1 if A / B or A % B would overflow. Mathematically, % + should never overflow, but on x86-like hosts INT_MIN % -1 traps, + and the C standard permits this, so treat this as an overflow too. + Do not check for division by zero; the caller can check this as + needed. */ +#define DIVIDE_OVERFLOW(a, b, min, max) \ + ((min) < 0 && (b) == -1 && (a) < - (max)) + +/* Return 1 if A << B would overflow. Here, MIN and MAX are for A only. + The C standard says that behavior is undefined for shifts unless + 0 <= B < wordwidth, and that when A is negative then A << B has + undefined behavior and A >> B has implementation-defined behavior, + but do not check these other restrictions; the caller can check + these as needed. */ +#define LSHIFT_OVERFLOW(a, b, min, max) \ + ((a) < 0 \ + ? (a) < (min) >> (b) \ + : (max) >> (b) < (a)) + +#endif diff --git a/modules/intoverflow b/modules/intoverflow new file mode 100644 index 0000000..950deee --- /dev/null +++ b/modules/intoverflow @@ -0,0 +1,20 @@ +Description: +Check for integer overflow. + +Files: +lib/intoverflow.h + +Depends-on: + +configure.ac: + +Makefile.am: + +Include: +"intoverflow.h" + +License: +LGPLv2+ + +Maintainer: +Paul Eggert
