postgres.git / summary / log / commit / refs
commit 4f4a0010a3a1e0404198130ac3cababeaa17d1e6
Author: Dean Rasheed <dean.a.rasheed@gmail.com>
Date: Thu Nov 09 09:56:31 2023 +0000
First released in: 17.0, 12.18, 13.14, 14.11, 15.6, 16.2
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
src/include/common/int.h | 6 +++++-
src/test/regress/expected/int8.out | 2 ++
src/test/regress/sql/int8.sql | 1 +
3 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/src/include/common/int.h b/src/include/common/int.h
index a2972218e72..4c862651f5d 100644
--- a/src/include/common/int.h
+++ b/src/include/common/int.h
@@ -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;
diff --git a/src/test/regress/expected/int8.out b/src/test/regress/expected/int8.out
index 813e3a82866..1bc3776208e 100644
--- a/src/test/regress/expected/int8.out
+++ b/src/test/regress/expected/int8.out
@@ -659,6 +659,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;
diff --git a/src/test/regress/sql/int8.sql b/src/test/regress/sql/int8.sql
index dba3ade687a..29712209d58 100644
--- a/src/test/regress/sql/int8.sql
+++ b/src/test/regress/sql/int8.sql
@@ -131,6 +131,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;
[parent: 319310aa1212]