Skip to content

Commit d522bd5

Browse files
authored
Merge pull request mruby#6768 from hasumikin/fix/envadjust
2 parents ac9f7ae + d95ebe4 commit d522bd5

File tree

1 file changed

+16
-6
lines changed

1 file changed

+16
-6
lines changed

src/vm.c

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -134,19 +134,29 @@ static inline void
134134
envadjust(mrb_state *mrb, mrb_value *oldbase, mrb_value *newbase)
135135
{
136136
mrb_callinfo *ci = mrb->c->cibase;
137-
ptrdiff_t delta = newbase - oldbase;
138-
139-
if (delta == 0) return;
137+
/*
138+
* Byte-level calculation to avoid truncation when allocator alignment is
139+
* smaller than sizeof(mrb_value).
140+
* eg: MRB_NO_BOXING + MRB_INT64 with MRB_32BIT => sizeof(mrb_value)=16
141+
* And when memory allocator's alignment is 8 bytes
142+
* Pointer subtraction on mrb_value* would truncate (8/16 -> 0).
143+
* So, we use char* for pointer calculation to get the correct offset in bytes,
144+
* then apply that offset to mrb_value* pointers.
145+
*/
146+
ptrdiff_t off = (char *)newbase - (char *)oldbase;
147+
148+
if (off == 0) return;
140149
while (ci <= mrb->c->ci) {
141150
struct REnv *e = mrb_vm_ci_env(ci);
142151

152+
mrb_value *new_stack = (mrb_value *)((char *)ci->stack + off);
153+
143154
if (e) {
144155
mrb_assert(e->cxt == mrb->c && MRB_ENV_ONSTACK_P(e));
145156
mrb_assert(e->stack == ci->stack);
146-
147-
e->stack += delta;
157+
e->stack = new_stack;
148158
}
149-
ci->stack += delta;
159+
ci->stack = new_stack;
150160
ci++;
151161
}
152162
}

0 commit comments

Comments
 (0)