]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
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;
                                }