From e3559c7b64e7963e3515c2ebfd7f1abad810ed19 Mon Sep 17 00:00:00 2001 From: Dana Robinson <43805+derobins@users.noreply.github.com> Date: Sat, 3 Jun 2023 07:23:35 -0700 Subject: Add casts to type conversion to fix long dbl bug (#3038) If a user buffer is misaligned in the type conversion code, memcpy could fail if the call is SSE-optimized by the compiler. This change adds uint8_t * casts so the compiler won't make optimistic assumptions about buffer alignment. --- src/H5Tconv.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/src/H5Tconv.c b/src/H5Tconv.c index 93ca59f..8118eb0 100644 --- a/src/H5Tconv.c +++ b/src/H5Tconv.c @@ -887,7 +887,17 @@ done: /* Macro defining action on source data which needs to be aligned (before main action) */ #define H5T_CONV_LOOP_PRE_SALIGN(ST) \ { \ - H5MM_memcpy(&src_aligned, src, sizeof(ST)); \ + /* The uint8_t * cast is required to avoid tripping over undefined behavior. \ + * \ + * The typed pointer arrives via a void pointer, which may have any alignment. \ + * We then cast it to a pointer to a type that is assumed to be aligned, which \ + * is undefined behavior (section 6.3.2.3 paragraph 7 of the C99 standard). \ + * In the past this hasn't caused many problems, but in some cases (e.g. \ + * converting long doubles on macOS), an optimizing compiler might do the \ + * wrong thing (in the macOS case, the conversion uses SSE, which has stricter \ + * requirements about alignment). \ + */ \ + H5MM_memcpy(&src_aligned, (const uint8_t *)src, sizeof(ST)); \ } /* Macro defining action on source data which doesn't need to be aligned (before main action) */ @@ -919,7 +929,17 @@ done: /* Macro defining action on destination data which needs to be aligned (after main action) */ #define H5T_CONV_LOOP_POST_DALIGN(DT) \ { \ - H5MM_memcpy(dst, &dst_aligned, sizeof(DT)); \ + /* The uint8_t * cast is required to avoid tripping over undefined behavior. \ + * \ + * The typed pointer arrives via a void pointer, which may have any alignment. \ + * We then cast it to a pointer to a type that is assumed to be aligned, which \ + * is undefined behavior (section 6.3.2.3 paragraph 7 of the C99 standard). \ + * In the past this hasn't caused many problems, but in some cases (e.g. \ + * converting long doubles on macOS), an optimizing compiler might do the \ + * wrong thing (in the macOS case, the conversion uses SSE, which has stricter \ + * requirements about alignment). \ + */ \ + H5MM_memcpy((uint8_t *)dst, &dst_aligned, sizeof(DT)); \ } /* Macro defining action on destination data which doesn't need to be aligned (after main action) */ -- cgit v0.12