Skip to content

Commit 0e3e8fb

Browse files
committed
Fix corner-case 64-bit integer subtraction bug on some platforms.
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
1 parent a7db71e commit 0e3e8fb

File tree

3 files changed

+8
-1
lines changed

3 files changed

+8
-1
lines changed

src/include/common/int.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,8 +200,12 @@ pg_sub_s64_overflow(int64 a, int64 b, int64 *result)
200200
*result = (int64) res;
201201
return false;
202202
#else
203+
/*
204+
* Note: overflow is also possible when a == 0 and b < 0 (specifically,
205+
* when b == PG_INT64_MIN).
206+
*/
203207
if ((a < 0 && b > 0 && a < PG_INT64_MIN + b) ||
204-
(a > 0 && b < 0 && a > PG_INT64_MAX + b))
208+
(a >= 0 && b < 0 && a > PG_INT64_MAX + b))
205209
{
206210
*result = 0x5EED; /* to avoid spurious warnings */
207211
return true;

src/test/regress/expected/int8.out

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -679,6 +679,8 @@ select -('-9223372036854775807'::int8);
679679

680680
select -('-9223372036854775808'::int8);
681681
ERROR: bigint out of range
682+
select 0::int8 - '-9223372036854775808'::int8;
683+
ERROR: bigint out of range
682684
select '9223372036854775800'::int8 + '9223372036854775800'::int8;
683685
ERROR: bigint out of range
684686
select '-9223372036854775800'::int8 + '-9223372036854775800'::int8;

src/test/regress/sql/int8.sql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ select '9223372036854775808'::int8;
132132

133133
select -('-9223372036854775807'::int8);
134134
select -('-9223372036854775808'::int8);
135+
select 0::int8 - '-9223372036854775808'::int8;
135136

136137
select '9223372036854775800'::int8 + '9223372036854775800'::int8;
137138
select '-9223372036854775800'::int8 + '-9223372036854775800'::int8;

0 commit comments

Comments
 (0)