]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Fix corner-case 64-bit integer subtraction bug on some platforms.
authorDean Rasheed <dean.a.rasheed@gmail.com>
Thu, 9 Nov 2023 09:54:22 +0000 (09:54 +0000)
committerDean Rasheed <dean.a.rasheed@gmail.com>
Thu, 9 Nov 2023 09:54:22 +0000 (09:54 +0000)
When computing "0 - INT64_MIN", most platforms would report an
overflow error, which is correct. However, platforms without integer
overflow builtins or 128-bit integers would fail to spot the overflow,
and incorrectly return INT64_MIN.

Back-patch to all supported branches.

Patch be me. Thanks to Jian He for initial investigation, and Laurenz
Albe and Tom Lane for review.

Discussion: https://postgr.es/m/CAEZATCUNK-AZSD0jVdgkk0N%3DNcAXBWeAEX-QU9AnJPensikmdQ%40mail.gmail.com

src/include/common/int.h
src/test/regress/expected/int8.out
src/test/regress/sql/int8.sql

index 12a269d952210a0bbd21495cede5f653851d5761..e2617fbc5d2700a4cbb076d0c32e155ee8cd3a11 100644 (file)
@@ -200,8 +200,12 @@ pg_sub_s64_overflow(int64 a, int64 b, int64 *result)
        *result = (int64) res;
        return false;
 #else
+       /*
+        * Note: overflow is also possible when a == 0 and b < 0 (specifically,
+        * when b == PG_INT64_MIN).
+        */
        if ((a < 0 && b > 0 && a < PG_INT64_MIN + b) ||
-               (a > 0 && b < 0 && a > PG_INT64_MAX + b))
+               (a >= 0 && b < 0 && a > PG_INT64_MAX + b))
        {
                *result = 0x5EED;               /* to avoid spurious warnings */
                return true;
index 1ae23cf3f94f14635b3545579e7cb8282f44074e..329f3911dd0fab5406d423c6918abcd5034b271f 100644 (file)
@@ -654,6 +654,8 @@ select -('-9223372036854775807'::int8);
 
 select -('-9223372036854775808'::int8);
 ERROR:  bigint out of range
+select 0::int8 - '-9223372036854775808'::int8;
+ERROR:  bigint out of range
 select '9223372036854775800'::int8 + '9223372036854775800'::int8;
 ERROR:  bigint out of range
 select '-9223372036854775800'::int8 + '-9223372036854775800'::int8;
index 38b771964d79873fa7104473fa2cfff63901c234..8a3d5371d6764a9c7dde5e23200ee2e386b206a2 100644 (file)
@@ -126,6 +126,7 @@ select '9223372036854775808'::int8;
 
 select -('-9223372036854775807'::int8);
 select -('-9223372036854775808'::int8);
+select 0::int8 - '-9223372036854775808'::int8;
 
 select '9223372036854775800'::int8 + '9223372036854775800'::int8;
 select '-9223372036854775800'::int8 + '-9223372036854775800'::int8;