diff options
author | Robert Haas <rhaas@postgresql.org> | 2016-02-01 08:23:41 -0500 |
---|---|---|
committer | Robert Haas <rhaas@postgresql.org> | 2016-02-01 08:23:41 -0500 |
commit | 64f5edca2401f6c2f23564da9dd52e92d08b3a20 (patch) | |
tree | 15b5fa0c34d6b2d3bac61a0a5f61de1b70643a1a | |
parent | 89611c4dfa67630f7dcc25881c17cbd1b2e24ea1 (diff) | |
download | postgresql-64f5edca2401f6c2f23564da9dd52e92d08b3a20.tar.gz postgresql-64f5edca2401f6c2f23564da9dd52e92d08b3a20.zip |
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
-rw-r--r-- | src/bin/pgbench/pgbench.c | 36 |
1 files changed, 34 insertions, 2 deletions
diff --git a/src/bin/pgbench/pgbench.c b/src/bin/pgbench/pgbench.c index 44da3d19c19..9bd822299b2 100644 --- a/src/bin/pgbench/pgbench.c +++ b/src/bin/pgbench/pgbench.c @@ -1047,7 +1047,29 @@ evaluateExpr(CState *st, PgBenchExpr *expr, int64 *retval) fprintf(stderr, "division by zero\n"); return false; } - *retval = lval / rval; + + /* + * 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; + return true; case '%': @@ -1056,7 +1078,17 @@ evaluateExpr(CState *st, PgBenchExpr *expr, int64 *retval) fprintf(stderr, "division by zero\n"); return false; } - *retval = lval % rval; + + /* + * 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; + return true; } |