Earlier quoted context omitted.
Looks like it is fixed now: $ expr \( -2147483648 \) \* -1 2147483648 $ expr \( -2147483648 \) / -1 2147483648 $ uname -srm FreeBSD 10.0-RELEASE amd64 Or maybe it doesn't work on i386?
It's likely an i386 thing: $ echo | awk '{ print 2 ** 31 }' 2147483648 Make sure you are using /bin/expr and maybe give -9223372036854775808 a whirl too.
$ which expr
/bin/expr
$ expr \( -9223372036854775808 \) \* -1
-9223372036854775808
$ expr \( -9223372036854775808 \) / -1
expr: overflow
Looking at the source code: void
assert_times(intmax_t a, intmax_t b, intmax_t r)
{
/*
* if first operand is 0, no overflow is possible,
* else result of division test must match second operand
*/
if (a != 0 && r / a != b)
errx(ERR_EXIT, "overflow");
}
struct val *
op_times(struct val *a, struct val *b)
{
struct val *r;
assert_to_integer(a);
assert_to_integer(b);
r = make_integer(a->u.i * b->u.i);
assert_times(a->u.i, b->u.i, r->u.i);
free_value(a);
free_value(b);
return (r);
}
void
assert_div(intmax_t a, intmax_t b)
{
if (b == 0)
errx(ERR_EXIT, "division by zero");
/* only INTMAX_MIN / -1 causes overflow */
if (a == INTMAX_MIN && b == -1)
errx(ERR_EXIT, "overflow");
}
struct val *
op_div(struct val *a, struct val *b)
{
struct val *r;
assert_to_integer(a);
assert_to_integer(b);
/* assert based on operands only, not on result */
assert_div(a->u.i, b->u.i);
r = make_integer(a->u.i / b->u.i);
free_value(a);
free_value(b);
return (r);
}
Looks like the check for overflow in the multiplication case is broken since the check itself does not account for overflow. I'll try to remember to submit a patch when I get home.