Commit 219a087
Fix misaligned memory access in
* Fix misaligned memory access in `LossyDctDecoder_execute` HALF→FLOAT expansion
After DCT decoding, `LossyDctDecoder_execute()` expands FLOAT-type channels
from their intermediate HALF (16-bit) XDR representation back to FLOAT (32-bit)
XDR in place. The expansion was done by casting `_rows[y]` (a `uint8_t *`)
directly to `float *` and `uint16_t *`, then reading and writing through those
typed pointers.
Because row buffers are assigned by advancing a byte pointer with no alignment
padding (`outBufferEnd += chan->width * chan->bytes_per_element` in
`internal_dwa_compressor.h`), a FLOAT channel that follows a HALF channel of
odd width receives a `_rows[y]` pointer that is 2-byte aligned but not 4-byte
aligned. Dereferencing a `float *` cast from such a pointer is undefined
behavior under the C standard:
- On ARM, RISC-V, and MIPS (strict alignment) this crashes immediately.
- On x86 it is silently tolerated at the hardware level but remains UB:
auto-vectorizing compilers (SSE/AVX) may assume aligned access and generate
incorrect code.
- UBSan reports: `store to misaligned address ... for type 'float', which
requires 4 byte alignment` at `internal_dwa_decoder.h:749`.
Fix: replace the cast-and-dereference pattern with the `unaligned_load16` /
`memcpy` / `unaligned_store32` helpers already used throughout the rest of
OpenEXRCore (`internal_xdr.h`, `unpack.c`, `pack.c`, `internal_pxr24.c`).
These helpers use `memcpy` internally, which the C standard guarantees is safe
for unaligned addresses and which compilers compile to a single load/store
instruction on architectures that support it.
The byte-order handling is preserved correctly:
- `unaligned_load16` reads 2 bytes via `memcpy` and applies `one_to_native16`
(XDR → native), returning a native-endian HALF value.
- `half_to_float` converts native HALF → native float.
- `memcpy(&bits, &f, 4)` reinterprets the float's bit pattern as `uint32_t`
without numeric conversion (the correct type-pun idiom in C).
- `unaligned_store32` applies `one_from_native32` (native → XDR) and writes
4 bytes via `memcpy`, storing the result in XDR float format.
Made-with: Cursor
Signed-off-by: Cary Phillips <cary@ilm.com>
* add TODO comment
Signed-off-by: Cary Phillips <cary@ilm.com>
---------
Signed-off-by: Cary Phillips <cary@ilm.com>LossyDctDecoder_execute HALF→FLOAT expansion (#2324)1 parent a764742 commit 219a087
1 file changed
Lines changed: 13 additions & 4 deletions
Lines changed: 13 additions & 4 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
651 | 651 | | |
652 | 652 | | |
653 | 653 | | |
654 | | - | |
655 | | - | |
| 654 | + | |
656 | 655 | | |
657 | 656 | | |
658 | 657 | | |
659 | | - | |
660 | | - | |
| 658 | + | |
| 659 | + | |
| 660 | + | |
| 661 | + | |
| 662 | + | |
| 663 | + | |
| 664 | + | |
| 665 | + | |
| 666 | + | |
| 667 | + | |
| 668 | + | |
| 669 | + | |
661 | 670 | | |
662 | 671 | | |
663 | 672 | | |
| |||
0 commit comments