diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2019-11-07 11:22:52 -0500 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2019-11-07 11:22:58 -0500 |
commit | a7145f6bc8b7774a29f3841552a463fb20ea98d7 (patch) | |
tree | 18e902b66a9955fe8b47d9d6f819cf57060c2e65 /src/include/c.h | |
parent | effa40281bb1f6c71e81c980f86852ab3be603c3 (diff) | |
download | postgresql-a7145f6bc8b7774a29f3841552a463fb20ea98d7.tar.gz |
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
Diffstat (limited to 'src/include/c.h')
-rw-r--r-- | src/include/c.h | 24 |
1 files changed, 24 insertions, 0 deletions
diff --git a/src/include/c.h b/src/include/c.h index 16b428daa1..c95acd35f7 100644 --- a/src/include/c.h +++ b/src/include/c.h @@ -1030,6 +1030,30 @@ extern void ExceptionalCondition(const char *conditionName, *_start++ = 0; \ } while (0) +/* + * Macros for range-checking float values before converting to integer. + * We must be careful here that the boundary values are expressed exactly + * in the float domain. PG_INTnn_MIN is an exact power of 2, so it will + * be represented exactly; but PG_INTnn_MAX isn't, and might get rounded + * off, so avoid using that. + * The input must be rounded to an integer beforehand, typically with rint(), + * else we might draw the wrong conclusion about close-to-the-limit values. + * These macros will do the right thing for Inf, but not necessarily for NaN, + * so check isnan(num) first if that's a possibility. + */ +#define FLOAT4_FITS_IN_INT16(num) \ + ((num) >= (float4) PG_INT16_MIN && (num) < -((float4) PG_INT16_MIN)) +#define FLOAT4_FITS_IN_INT32(num) \ + ((num) >= (float4) PG_INT32_MIN && (num) < -((float4) PG_INT32_MIN)) +#define FLOAT4_FITS_IN_INT64(num) \ + ((num) >= (float4) PG_INT64_MIN && (num) < -((float4) PG_INT64_MIN)) +#define FLOAT8_FITS_IN_INT16(num) \ + ((num) >= (float8) PG_INT16_MIN && (num) < -((float8) PG_INT16_MIN)) +#define FLOAT8_FITS_IN_INT32(num) \ + ((num) >= (float8) PG_INT32_MIN && (num) < -((float8) PG_INT32_MIN)) +#define FLOAT8_FITS_IN_INT64(num) \ + ((num) >= (float8) PG_INT64_MIN && (num) < -((float8) PG_INT64_MIN)) + /* ---------------------------------------------------------------- * Section 8: random stuff |