pgbench: Install guards against obscure overflow conditions.
Dividing INT_MIN by -1 or taking INT_MIN modulo -1 can sometimes cause floating-point exceptions or otherwise misbehave. Fabien Coelho and Michael Paquier
This commit is contained in:
parent
89611c4dfa
commit
64f5edca24
@ -1047,7 +1047,29 @@ evaluateExpr(CState *st, PgBenchExpr *expr, int64 *retval)
|
|||||||
fprintf(stderr, "division by zero\n");
|
fprintf(stderr, "division by zero\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* INT64_MIN / -1 is problematic, since the result
|
||||||
|
* can't be represented on a two's-complement machine.
|
||||||
|
* Some machines produce INT64_MIN, some produce zero,
|
||||||
|
* some throw an exception. We can dodge the problem
|
||||||
|
* by recognizing that division by -1 is the same as
|
||||||
|
* negation.
|
||||||
|
*/
|
||||||
|
if (rval == -1)
|
||||||
|
{
|
||||||
|
*retval = -lval;
|
||||||
|
|
||||||
|
/* overflow check (needed for INT64_MIN) */
|
||||||
|
if (lval == PG_INT64_MIN)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "bigint out of range\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
*retval = lval / rval;
|
*retval = lval / rval;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case '%':
|
case '%':
|
||||||
@ -1056,7 +1078,17 @@ evaluateExpr(CState *st, PgBenchExpr *expr, int64 *retval)
|
|||||||
fprintf(stderr, "division by zero\n");
|
fprintf(stderr, "division by zero\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Some machines throw a floating-point exception for
|
||||||
|
* INT64_MIN % -1. Dodge that problem by noting that
|
||||||
|
* any value modulo -1 is 0.
|
||||||
|
*/
|
||||||
|
if (rval == -1)
|
||||||
|
*retval = 0;
|
||||||
|
else
|
||||||
*retval = lval % rval;
|
*retval = lval % rval;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user