Decide inf/nan on the bit pattern in H5Zconfig_get_double()

The guard rejecting inf/nan filter parameters called isnan() and isinf().
Both are folded to 0 under a fast-math build -- gcc/clang -ffast-math or
-ffinite-math-only, and Intel icx's -fp-model=fast, which is its default at
-O2 and above -- so on exactly the Intel oneAPI configuration this branch
already had to work around for the vendored TOML parser, the guard passes
everything and an inf reaches *out as a filter parameter.

Measured with gcc: -O2 gives isinf(inf) = 1, -O2 -ffast-math gives 0.

Test the exponent bits instead, via a new H5Z__fp64_is_inf_or_nan() helper:
an exponent field of all ones is inf (zero mantissa) or nan (nonzero).
That is immune to both compile-time folding and to ambient FTZ/DAZ.  The
helper keeps the isnan()/isinf() spelling for the H5_SIZEOF_DOUBLE != 8
case, where the bit layout cannot be assumed.
This commit is contained in:
Scot Breitenfeld
2026-09-08 00:02:17 -05:00
parent 9db35be232
commit 1d7a1d3b80
+22 -1
View File
@@ -657,6 +657,27 @@ H5Zconfig_get_int(const char *params, const char *key, int64_t *out)
FUNC_LEAVE_API_NOINIT_NOLOCK(ret_value)
}
/* Is v an inf or a nan?
*
* Decided on the bit pattern rather than with isnan()/isinf(): a fast-math
* build -- Intel icx's -fp-model=fast (its default at -O2 and above), or
* gcc/clang -ffast-math or -ffinite-math-only -- may assume no operand is
* ever inf or nan and fold both classifiers to 0, letting through exactly
* the values the caller means to reject. An exponent field of all ones is
* inf (zero mantissa) or nan (nonzero mantissa). */
static inline bool
H5Z__fp64_is_inf_or_nan(double v)
{
#if H5_SIZEOF_DOUBLE == 8
uint64_t bits;
memcpy(&bits, &v, sizeof(v));
return (bits & 0x7ff0000000000000ULL) == 0x7ff0000000000000ULL;
#else
return isnan(v) || isinf(v);
#endif
}
/*-------------------------------------------------------------------------
* Function: H5Zconfig_get_double
*
@@ -690,7 +711,7 @@ H5Zconfig_get_double(const char *params, const char *key, double *out)
if (d.type != TOML_FP64)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "type mismatch: key '%s' is not a TOML float", key);
if (isnan(d.u.fp64) || isinf(d.u.fp64))
if (H5Z__fp64_is_inf_or_nan(d.u.fp64))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
"inf/nan float values are not supported for filter parameters (key '%s')", key);
*out = d.u.fp64;