mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
d95ebe4a23
This patch fixes a bug in the stack extension logic that could cause a HardFault on certain configurations when the stack is reallocated to a new address. ## Background When the mruby VM's stack runs out, stack_extend_alloc() calls mrb_realloc to grow it. If reallocation moves the block to a new address, envadjust() adjusts all ci->stack pointers to point into the new allocation. ## The bug The bug happened under the configuration below: - MRB_INT64 on MRB_32BIT (`sizeof(mrb_value) == 16` because MRB_NO_BOXING is now mandatory) - Allocator with 8-byte alignment (eg. PICORB_ALLOC_ALIGN=8 in PicoRuby for Raspi Pico) The delta was computed via mrb_value* pointer subtraction: ```c ptrdiff_t delta = newbase - oldbase; // units of sizeof(mrb_value) ``` If : - Old address: 0x2004c508 - New address: 0x2004c510 (8-byte difference) The pointer subtraction truncated: 8 / 16 = 0. envadjust() was misleaded as `delta == 0` and returned early without adjusting any ci->stack pointers. The stbase was updated to the new address, but all stack pointers still pointed 8 bytes before it. Every register access was shifted, reading garbage, ultimately causing a HardFault. ## The fix Byte-level char* calculation instead of mrb_value* calculation: ```c ptrdiff_t off = (char*)newbase - (char*)oldbase; // ... ci->stack = (mrb_value*)((char*)ci->stack + off); ``` This ensures the adjustment is exact regardless of sizeof(mrb_value) and allocator alignment.