From d288f4c9570fefe66b85e54a5dfb068c3874fd30 Mon Sep 17 00:00:00 2001 From: Jakub Gonet Date: Wed, 17 Dec 2025 16:24:08 +0100 Subject: [PATCH] Fix floats on Wasm On wasm32, terms are aligned by 4 bytes. `memory_heap_allocation` returns a pointer for `n` terms. We used float_term_t to create an union between a term and float. However, floats are aligned to 8 bytes which made casting between union and term pointers unsafe. We replaced union usage to `memcpy` which allows unaligned memory access. The true solution would be to return correctly aligned memory from memory_heap_alloc but fix for that would need a lot more testing. Signed-off-by: Jakub Gonet --- src/libAtomVM/term.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/libAtomVM/term.h b/src/libAtomVM/term.h index 116411b3e..393a91fd4 100644 --- a/src/libAtomVM/term.h +++ b/src/libAtomVM/term.h @@ -2396,16 +2396,18 @@ static inline term term_from_float(avm_float_t f, Heap *heap) term *boxed_value = memory_heap_alloc(heap, FLOAT_SIZE); boxed_value[0] = ((FLOAT_SIZE - 1) << 6) | TERM_BOXED_FLOAT; - float_term_t *boxed_float = (float_term_t *) (boxed_value + 1); - boxed_float->f = f; - + // For wasm32, alignof(avm_float_t) = 8 and alignof(term) = 4 + // `memory_heap_alloc` returns memory aligned to term size. + memcpy(boxed_value + 1, &f, sizeof(avm_float_t)); return ((term) boxed_value) | TERM_PRIMARY_BOXED; } static inline avm_float_t term_to_float(term t) { - const float_term_t *boxed_float = (float_term_t *) (term_to_const_term_ptr(t) + 1); - return boxed_float->f; + avm_float_t result; + // see `term_from_float` + memcpy(&result, term_to_const_term_ptr(t) + 1, sizeof(avm_float_t)); + return result; } static inline bool term_is_number(term t)