From 64f5edca2401f6c2f23564da9dd52e92d08b3a20 Mon Sep 17 00:00:00 2001
From: Robert Haas <rhaas@postgresql.org>
Date: Mon, 1 Feb 2016 08:23:41 -0500
Subject: [PATCH] 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
---
 src/bin/pgbench/pgbench.c | 36 ++++++++++++++++++++++++++++++++++--
 1 file 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;
 				}
 
-- 
GitLab