Tweak the overflow checks in integer division functions to complain if the
authorTom Lane <tgl@sss.pgh.pa.us>
Sun, 5 Oct 2008 23:18:37 +0000 (23:18 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sun, 5 Oct 2008 23:18:37 +0000 (23:18 +0000)
machine produces zero (rather than the more usual minimum-possible-integer)
for the only possible overflow case.  This has been seen to occur for at least
some word widths on some hardware, and it's cheap enough to check for
everywhere.  Per Peter's analysis of buildfarm reports.

This could be back-patched, but in the absence of any gripes from the field
I doubt it's worth the trouble.

src/backend/utils/adt/int.c
src/backend/utils/adt/int8.c

index c8dfe1cfeb71e25f66a8ff193db132a57c29d0a7..854e8a457998e17458739f9cb0acfa05f3587477 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/utils/adt/int.c,v 1.82 2008/06/17 19:10:56 tgl Exp $
+ *   $PostgreSQL: pgsql/src/backend/utils/adt/int.c,v 1.83 2008/10/05 23:18:37 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -735,9 +735,10 @@ int4div(PG_FUNCTION_ARGS)
    /*
     * Overflow check.  The only possible overflow case is for arg1 = INT_MIN,
     * arg2 = -1, where the correct result is -INT_MIN, which can't be
-    * represented on a two's-complement machine.
+    * represented on a two's-complement machine.  Most machines produce
+    * INT_MIN but it seems some produce zero.
     */
-   if (arg2 == -1 && arg1 < 0 && result < 0)
+   if (arg2 == -1 && arg1 < 0 && result <= 0)
        ereport(ERROR,
                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
                 errmsg("integer out of range")));
@@ -863,9 +864,10 @@ int2div(PG_FUNCTION_ARGS)
    /*
     * Overflow check.  The only possible overflow case is for arg1 =
     * SHRT_MIN, arg2 = -1, where the correct result is -SHRT_MIN, which can't
-    * be represented on a two's-complement machine.
+    * be represented on a two's-complement machine.  Most machines produce
+    * SHRT_MIN but it seems some produce zero.
     */
-   if (arg2 == -1 && arg1 < 0 && result < 0)
+   if (arg2 == -1 && arg1 < 0 && result <= 0)
        ereport(ERROR,
                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
                 errmsg("smallint out of range")));
@@ -1041,9 +1043,10 @@ int42div(PG_FUNCTION_ARGS)
    /*
     * Overflow check.  The only possible overflow case is for arg1 = INT_MIN,
     * arg2 = -1, where the correct result is -INT_MIN, which can't be
-    * represented on a two's-complement machine.
+    * represented on a two's-complement machine.  Most machines produce
+    * INT_MIN but it seems some produce zero.
     */
-   if (arg2 == -1 && arg1 < 0 && result < 0)
+   if (arg2 == -1 && arg1 < 0 && result <= 0)
        ereport(ERROR,
                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
                 errmsg("integer out of range")));
index dc56df4d186dbf5cb42fa3a3cc97711b9f00dfbd..550c06f5d079c80e824c0ca56efe3f588a70104a 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/utils/adt/int8.c,v 1.70 2008/06/17 19:10:56 tgl Exp $
+ *   $PostgreSQL: pgsql/src/backend/utils/adt/int8.c,v 1.71 2008/10/05 23:18:37 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -608,9 +608,10 @@ int8div(PG_FUNCTION_ARGS)
    /*
     * Overflow check.  The only possible overflow case is for arg1 =
     * INT64_MIN, arg2 = -1, where the correct result is -INT64_MIN, which
-    * can't be represented on a two's-complement machine.
+    * can't be represented on a two's-complement machine.  Most machines
+    * produce INT64_MIN but it seems some produce zero.
     */
-   if (arg2 == -1 && arg1 < 0 && result < 0)
+   if (arg2 == -1 && arg1 < 0 && result <= 0)
        ereport(ERROR,
                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
                 errmsg("bigint out of range")));
@@ -830,9 +831,10 @@ int84div(PG_FUNCTION_ARGS)
    /*
     * Overflow check.  The only possible overflow case is for arg1 =
     * INT64_MIN, arg2 = -1, where the correct result is -INT64_MIN, which
-    * can't be represented on a two's-complement machine.
+    * can't be represented on a two's-complement machine.  Most machines
+    * produce INT64_MIN but it seems some produce zero.
     */
-   if (arg2 == -1 && arg1 < 0 && result < 0)
+   if (arg2 == -1 && arg1 < 0 && result <= 0)
        ereport(ERROR,
                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
                 errmsg("bigint out of range")));
@@ -1008,9 +1010,10 @@ int82div(PG_FUNCTION_ARGS)
    /*
     * Overflow check.  The only possible overflow case is for arg1 =
     * INT64_MIN, arg2 = -1, where the correct result is -INT64_MIN, which
-    * can't be represented on a two's-complement machine.
+    * can't be represented on a two's-complement machine.  Most machines
+    * produce INT64_MIN but it seems some produce zero.
     */
-   if (arg2 == -1 && arg1 < 0 && result < 0)
+   if (arg2 == -1 && arg1 < 0 && result <= 0)
        ereport(ERROR,
                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
                 errmsg("bigint out of range")));