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
This commit is contained in:
parent
99fa98766f
commit
dea12b40d5
@ -200,8 +200,12 @@ pg_sub_s64_overflow(int64 a, int64 b, int64 *result)
|
|||||||
*result = (int64) res;
|
*result = (int64) res;
|
||||||
return false;
|
return false;
|
||||||
#else
|
#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) ||
|
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 */
|
*result = 0x5EED; /* to avoid spurious warnings */
|
||||||
return true;
|
return true;
|
||||||
|
@ -659,6 +659,8 @@ select -('-9223372036854775807'::int8);
|
|||||||
|
|
||||||
select -('-9223372036854775808'::int8);
|
select -('-9223372036854775808'::int8);
|
||||||
ERROR: bigint out of range
|
ERROR: bigint out of range
|
||||||
|
select 0::int8 - '-9223372036854775808'::int8;
|
||||||
|
ERROR: bigint out of range
|
||||||
select '9223372036854775800'::int8 + '9223372036854775800'::int8;
|
select '9223372036854775800'::int8 + '9223372036854775800'::int8;
|
||||||
ERROR: bigint out of range
|
ERROR: bigint out of range
|
||||||
select '-9223372036854775800'::int8 + '-9223372036854775800'::int8;
|
select '-9223372036854775800'::int8 + '-9223372036854775800'::int8;
|
||||||
|
@ -131,6 +131,7 @@ select '9223372036854775808'::int8;
|
|||||||
|
|
||||||
select -('-9223372036854775807'::int8);
|
select -('-9223372036854775807'::int8);
|
||||||
select -('-9223372036854775808'::int8);
|
select -('-9223372036854775808'::int8);
|
||||||
|
select 0::int8 - '-9223372036854775808'::int8;
|
||||||
|
|
||||||
select '9223372036854775800'::int8 + '9223372036854775800'::int8;
|
select '9223372036854775800'::int8 + '9223372036854775800'::int8;
|
||||||
select '-9223372036854775800'::int8 + '-9223372036854775800'::int8;
|
select '-9223372036854775800'::int8 + '-9223372036854775800'::int8;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user