From 74267ce91eb4c117c0e35fb575334d3f8b7c2c83 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sun, 1 Mar 2026 23:08:53 +0900 Subject: [PATCH] error.h: fix RBreak size overflow on 32-bit platforms with MRB_NO_BOXING On 32-bit platforms where alignof(int64_t) == 8 (ARM, MIPS, PowerPC, RISC-V, MinGW), struct RBreak with MRB_USE_RBREAK_VALUE_UNION was 24 bytes (6 words) due to alignment padding before the union mrb_value_union field. This exceeds the 5-word RVALUE limit, causing a static assertion failure. Replace union mrb_value_union with uint32_t[] storage (alignof == 4) and use memcpy for value access. This gives exactly 20 bytes on all 32-bit platforms. Ref #6722 Co-authored-by: Claude --- include/mruby/error.h | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/include/mruby/error.h b/include/mruby/error.h index dbff17cd1..63a45ee96 100644 --- a/include/mruby/error.h +++ b/include/mruby/error.h @@ -8,6 +8,7 @@ #define MRUBY_ERROR_H #include "common.h" +#include /** * mruby error handling. @@ -53,7 +54,11 @@ struct RBreak { #ifndef MRB_USE_RBREAK_VALUE_UNION mrb_value val; #else - union mrb_value_union value; + /* Store value as uint32_t words instead of union mrb_value_union + to avoid 8-byte alignment of int64_t/double on 32-bit platforms + (e.g., ARM, MIPS, PowerPC) which would inflate struct size beyond + the 5-word RVALUE limit due to padding. */ + uint32_t value[sizeof(union mrb_value_union) / sizeof(uint32_t)]; #endif }; @@ -66,14 +71,14 @@ static inline mrb_value mrb_break_value_get(struct RBreak *brk) { mrb_value val; - val.value = brk->value; + memcpy(&val.value, brk->value, sizeof(val.value)); val.tt = (enum mrb_vtype)(brk->flags & RBREAK_VALUE_TT_MASK); return val; } static inline void mrb_break_value_set(struct RBreak *brk, mrb_value val) { - brk->value = val.value; + memcpy(brk->value, &val.value, sizeof(val.value)); brk->flags &= ~RBREAK_VALUE_TT_MASK; brk->flags |= val.tt; }