diff options
author | Dana Robinson <43805+derobins@users.noreply.github.com> | 2023-11-07 16:13:30 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-11-07 16:13:30 (GMT) |
commit | e0d095ebf020706ec7d7c82e6674b18f1a0a2d5b (patch) | |
tree | 81df13653837d46588c856bee0cf7fcbd7779d2f /src | |
parent | ec695cf34f7256d7af9bbc2fcf5366da0119fcea (diff) | |
download | hdf5-e0d095ebf020706ec7d7c82e6674b18f1a0a2d5b.zip hdf5-e0d095ebf020706ec7d7c82e6674b18f1a0a2d5b.tar.gz hdf5-e0d095ebf020706ec7d7c82e6674b18f1a0a2d5b.tar.bz2 |
Disable FP exceptions in H5T init code (#3837)
The H5T floating-point datatype initialization code can raise exceptions when handling signaling NaNs. This change disables FE_INVALID exceptions during initialization.
Also removes the -ieee=full change for NAG Fortran as that shouldn't be necessary anymore.
Fixes #3831
Diffstat (limited to 'src')
-rw-r--r-- | src/H5Tinit_float.c | 54 | ||||
-rw-r--r-- | src/H5private.h | 1 |
2 files changed, 37 insertions, 18 deletions
diff --git a/src/H5Tinit_float.c b/src/H5Tinit_float.c index 3b9e127..3213f00 100644 --- a/src/H5Tinit_float.c +++ b/src/H5Tinit_float.c @@ -51,19 +51,23 @@ * Function: DETECT_F * * Purpose: This macro takes a floating point type like `double' and - * a base name like `natd' and detects byte order, mantissa - * location, exponent location, sign bit location, presence or - * absence of implicit mantissa bit, and exponent bias and - * initializes a detected_t structure with those properties. + * and detects byte order, mantissa location, exponent location, + * sign bit location, presence or absence of implicit mantissa + * bit, and exponent bias and initializes a detected_t structure + * with those properties. + * + * Note that these operations can raise floating-point + * exceptions and building with some compiler options + * (especially Fortran) can cause problems. *------------------------------------------------------------------------- */ -#define DETECT_F(TYPE, VAR, INFO) \ +#define DETECT_F(TYPE, INFO) \ do { \ - TYPE _v1, _v2, _v3; \ - unsigned char _buf1[sizeof(TYPE)], _buf3[sizeof(TYPE)]; \ - unsigned char _pad_mask[sizeof(TYPE)]; \ - unsigned char _byte_mask; \ - int _i, _j, _last = (-1); \ + TYPE _v1, _v2, _v3; \ + uint8_t _buf1[sizeof(TYPE)], _buf3[sizeof(TYPE)]; \ + uint8_t _pad_mask[sizeof(TYPE)]; \ + uint8_t _byte_mask; \ + int _i, _j, _last = -1; \ \ memset(&INFO, 0, sizeof(INFO)); \ INFO.size = sizeof(TYPE); \ @@ -81,7 +85,7 @@ _v1 = (TYPE)4.0L; \ H5MM_memcpy(_buf1, (const void *)&_v1, sizeof(TYPE)); \ for (_i = 0; _i < (int)sizeof(TYPE); _i++) \ - for (_byte_mask = (unsigned char)1; _byte_mask; _byte_mask = (unsigned char)(_byte_mask << 1)) { \ + for (_byte_mask = (uint8_t)1; _byte_mask; _byte_mask = (uint8_t)(_byte_mask << 1)) { \ _buf1[_i] ^= _byte_mask; \ H5MM_memcpy((void *)&_v2, (const void *)_buf1, sizeof(TYPE)); \ H5_GCC_CLANG_DIAG_OFF("float-equal") \ @@ -118,7 +122,7 @@ _v1 = (TYPE)1.0L; \ _v2 = (TYPE)-1.0L; \ if (H5T__bit_cmp(sizeof(TYPE), INFO.perm, &_v1, &_v2, _pad_mask, &(INFO.sign)) < 0) \ - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "failed to detect byte order"); \ + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "failed to determine sign bit"); \ \ /* Mantissa */ \ INFO.mpos = 0; \ @@ -126,12 +130,11 @@ _v1 = (TYPE)1.0L; \ _v2 = (TYPE)1.5L; \ if (H5T__bit_cmp(sizeof(TYPE), INFO.perm, &_v1, &_v2, _pad_mask, &(INFO.msize)) < 0) \ - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "failed to detect byte order"); \ + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "failed to determine mantissa"); \ INFO.msize += 1 + (unsigned)(INFO.imp ? 0 : 1) - INFO.mpos; \ \ /* Exponent */ \ - INFO.epos = INFO.mpos + INFO.msize; \ - \ + INFO.epos = INFO.mpos + INFO.msize; \ INFO.esize = INFO.sign - INFO.epos; \ \ _v1 = (TYPE)1.0L; \ @@ -456,17 +459,24 @@ H5T__set_precision(H5T_fpoint_det_t *d) herr_t H5_NO_UBSAN H5T__init_native_float_types(void) { + fenv_t saved_fenv; H5T_fpoint_det_t det; H5T_t *dt = NULL; herr_t ret_value = SUCCEED; FUNC_ENTER_PACKAGE + /* Turn off floating-point exceptions while initializing to avoid + * tripping over signaling NaNs while looking at "don't care" bits. + */ + if (feholdexcept(&saved_fenv) != 0) + HSYS_GOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, FAIL, "can't save floating-point environment"); + /* H5T_NATIVE_FLOAT */ /* Get the type's characteristics */ memset(&det, 0, sizeof(H5T_fpoint_det_t)); - DETECT_F(float, FLOAT, det); + DETECT_F(float, det); /* Allocate and fill type structure */ if (NULL == (dt = H5T__alloc())) @@ -497,7 +507,7 @@ H5T__init_native_float_types(void) /* Get the type's characteristics */ memset(&det, 0, sizeof(H5T_fpoint_det_t)); - DETECT_F(double, DOUBLE, det); + DETECT_F(double, det); /* Allocate and fill type structure */ if (NULL == (dt = H5T__alloc())) @@ -528,7 +538,7 @@ H5T__init_native_float_types(void) /* Get the type's characteristics */ memset(&det, 0, sizeof(H5T_fpoint_det_t)); - DETECT_F(long double, LDOUBLE, det); + DETECT_F(long double, det); /* Allocate and fill type structure */ if (NULL == (dt = H5T__alloc())) @@ -561,6 +571,14 @@ H5T__init_native_float_types(void) H5T_native_order_g = det.order; done: + /* Clear any FE_INVALID exceptions from NaN handling */ + if (feclearexcept(FE_INVALID) != 0) + HSYS_GOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, FAIL, "can't clear floating-point exceptions"); + + /* Restore the original environment */ + if (feupdateenv(&saved_fenv) != 0) + HSYS_GOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, FAIL, "can't restore floating-point environment"); + if (ret_value < 0) { if (dt != NULL) { dt->shared = H5FL_FREE(H5T_shared_t, dt->shared); diff --git a/src/H5private.h b/src/H5private.h index 14a0ac3..3aaa0d5 100644 --- a/src/H5private.h +++ b/src/H5private.h @@ -26,6 +26,7 @@ #include <ctype.h> #include <errno.h> #include <fcntl.h> +#include <fenv.h> #include <float.h> #include <math.h> #include <setjmp.h> |