pgbench: Install guards against obscure overflow conditions.
authorRobert Haas <rhaas@postgresql.org>
Mon, 1 Feb 2016 13:23:41 +0000 (08:23 -0500)
committerRobert Haas <rhaas@postgresql.org>
Mon, 1 Feb 2016 13:26:07 +0000 (08:26 -0500)
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

index 1a3ba032822f729639e34783de75285ebd093713..1e1806fad9a3b17a8e74c9fbeabff6cabd5261a1 100644 (file)
@@ -961,7 +961,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 '%':
@@ -970,7 +992,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;
                }