From 15783d057543edde84b537815a8f22cf99d4beaa Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Thu, 7 Nov 2019 11:22:52 -0500 Subject: Fix integer-overflow edge case detection in interval_mul and pgbench. This patch adopts the overflow check logic introduced by commit cbdb8b4c0 into two more places. interval_mul() failed to notice if it computed a new microseconds value that was one more than INT64_MAX, and pgbench's double-to-int64 logic had the same sorts of edge-case problems that cbdb8b4c0 fixed in the core code. To make this easier to get right in future, put the guts of the checks into new macros in c.h, and add commentary about how to use the macros correctly. Back-patch to all supported branches, as we did with the previous fix. Yuya Watari Discussion: https://postgr.es/m/CAJ2pMkbkkFw2hb9Qb1Zj8d06EhWAQXFLy73St4qWv6aX=vqnjw@mail.gmail.com --- src/backend/utils/adt/int8.c | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) (limited to 'src/backend/utils/adt/int8.c') diff --git a/src/backend/utils/adt/int8.c b/src/backend/utils/adt/int8.c index 62f54c12d50..c04d3abcef8 100644 --- a/src/backend/utils/adt/int8.c +++ b/src/backend/utils/adt/int8.c @@ -1351,15 +1351,8 @@ dtoi8(PG_FUNCTION_ARGS) */ num = rint(num); - /* - * Range check. We must be careful here that the boundary values are - * expressed exactly in the float domain. We expect PG_INT64_MIN to be an - * exact power of 2, so it will be represented exactly; but PG_INT64_MAX - * isn't, and might get rounded off, so avoid using it. - */ - if (num < (float8) PG_INT64_MIN || - num >= -((float8) PG_INT64_MIN) || - isnan(num)) + /* Range check */ + if (isnan(num) || !FLOAT8_FITS_IN_INT64(num)) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("bigint out of range"))); @@ -1393,15 +1386,8 @@ ftoi8(PG_FUNCTION_ARGS) */ num = rint(num); - /* - * Range check. We must be careful here that the boundary values are - * expressed exactly in the float domain. We expect PG_INT64_MIN to be an - * exact power of 2, so it will be represented exactly; but PG_INT64_MAX - * isn't, and might get rounded off, so avoid using it. - */ - if (num < (float4) PG_INT64_MIN || - num >= -((float4) PG_INT64_MIN) || - isnan(num)) + /* Range check */ + if (isnan(num) || !FLOAT4_FITS_IN_INT64(num)) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("bigint out of range"))); -- cgit v1.2.3