1
0
mirror of git://git.sv.gnu.org/coreutils.git synced 2026-04-20 10:51:48 +02:00

(toarith): Rewrite to detect/diagnose integer overflow,

rather than suffering silently.
Before, expr would silently overflow and wrap around:
  $ expr 9223372036854775808 = 0   # $(echo 2^63|bc)
  1
Now it detects the problem and exits nonzero:
  $ ./expr $(echo 2^63|bc) = 0
  ./expr: 9223372036854775808: integer is too large
This commit is contained in:
Jim Meyering
2005-01-14 14:15:25 +00:00
parent 9eea266563
commit 7eff5901c4

View File

@@ -1,5 +1,5 @@
/* expr -- evaluate expressions.
Copyright (C) 86, 1991-1997, 1999-2004 Free Software Foundation, Inc.
Copyright (C) 86, 1991-1997, 1999-2005 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
@@ -322,34 +322,44 @@ tostring (VALUE *v)
static bool
toarith (VALUE *v)
{
intmax_t i;
bool neg;
char *cp;
switch (v->type)
{
case integer:
return true;
case string:
i = 0;
cp = v->u.s;
neg = (*cp == '-');
if (neg)
cp++;
{
intmax_t value = 0;
char *cp = v->u.s;
int sign = (*cp == '-' ? -1 : 1);
do
{
if (ISDIGIT (*cp))
i = i * 10 + *cp - '0';
else
return false;
}
while (*++cp);
if (sign < 0)
cp++;
free (v->u.s);
v->u.i = i * (neg ? -1 : 1);
v->type = integer;
return true;
do
{
if (ISDIGIT (*cp))
{
intmax_t new_v = 10 * value + sign * (*cp - '0');
if (0 < sign
? (INTMAX_MAX / 10 < value || new_v < 0)
: (value < INTMAX_MIN / 10 || 0 < new_v))
error (EXPR_FAILURE, 0,
(0 < sign
? _("integer is too large: %s")
: _("integer is too small: %s")),
quotearg_colon (v->u.s));
value = new_v;
}
else
return false;
}
while (*++cp);
free (v->u.s);
v->u.i = value * sign;
v->type = integer;
return true;
}
default:
abort ();
}