boxing_word.h: use memcpy-based RFloat access for unaligned 32-bit

On 32-bit with MRB_WORDBOX_NO_FLOAT_TRUNCATE, RFloat stores a double
(8-byte alignment) but GC heap slots only guarantee 4-byte alignment.
Use char array + memcpy accessors to avoid misaligned access (SIGBUS
on MIPS, undefined behavior per C standard).

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Yukihiro "Matz" Matsumoto
2026-02-27 10:08:37 +09:00
parent eaaa66b39b
commit 32f99a622d
3 changed files with 36 additions and 7 deletions
+30 -1
View File
@@ -14,8 +14,37 @@
#ifndef MRB_NO_FLOAT
struct RFloat {
MRB_OBJECT_HEADER;
#ifdef MRB_WORDBOX_NO_FLOAT_TRUNCATE
/* avoid 8-byte alignment on 32-bit; use memcpy-based accessors */
char f[sizeof(mrb_float)];
#else
mrb_float f;
#endif
};
#include <string.h>
static inline mrb_float
mrb_rfloat_value(const struct RFloat *p)
{
#ifdef MRB_WORDBOX_NO_FLOAT_TRUNCATE
mrb_float f;
memcpy(&f, p->f, sizeof(mrb_float));
return f;
#else
return p->f;
#endif
}
static inline void
mrb_rfloat_set(struct RFloat *p, mrb_float f)
{
#ifdef MRB_WORDBOX_NO_FLOAT_TRUNCATE
memcpy(p->f, &f, sizeof(mrb_float));
#else
p->f = f;
#endif
}
#endif
struct RInteger {
@@ -155,7 +184,7 @@ MRB_API mrb_value mrb_boxing_int_value(struct mrb_state*, mrb_int);
MRB_API mrb_float mrb_word_boxing_value_float(mrb_value v);
#define mrb_float(o) mrb_word_boxing_value_float(o)
#else
#define mrb_float(o) mrb_val_union(o).fp->f
#define mrb_float(o) mrb_rfloat_value(mrb_val_union(o).fp)
#endif
#endif
#define mrb_fixnum(o) (mrb_int)(((intptr_t)(o).w) >> WORDBOX_FIXNUM_SHIFT)