Skip to content

Commit

Permalink
vm: fix crash due to stale frame pointer
Browse files Browse the repository at this point in the history
In some cases, calls made while processing insns in uc_vm_execute_chunk can
lead to realloc of vm->callframes without reloading the current frame pointer.
This was observed with I_ADD (which can call an object's tostring method).
Instead of playing whac-a-mole with insns affecting the frame pointer, let's
reload it whenever necessary.

Signed-off-by: Felix Fietkau <[email protected]>
  • Loading branch information
nbd168 committed Feb 6, 2025
1 parent 00b172c commit c182101
Showing 1 changed file with 7 additions and 14 deletions.
21 changes: 7 additions & 14 deletions vm.c
Original file line number Diff line number Diff line change
Expand Up @@ -2771,14 +2771,18 @@ uc_vm_signal_dispatch(uc_vm_t *vm)
static uc_vm_status_t
uc_vm_execute_chunk(uc_vm_t *vm)
{
uc_callframe_t *frame = uc_vm_current_frame(vm);
uc_chunk_t *chunk = uc_vm_frame_chunk(frame);
uc_callframe_t *frame = NULL;
uc_chunk_t *chunk = NULL;
size_t caller = vm->callframes.count - 1;
uc_value_t *retval;
uc_vm_insn_t insn;
uint8_t *ip;

while (chunk && vm->callframes.count > caller) {
while (vm->callframes.count > caller) {
uc_callframe_t *prev_frame = uc_vm_current_frame(vm);
frame = uc_vm_current_frame(vm);
chunk = frame->closure ? uc_vm_frame_chunk(frame) : NULL;

if (vm->trace) {
ip = frame->ip;
insn = uc_vm_decode_insn(vm, frame, chunk);
Expand Down Expand Up @@ -2968,15 +2972,11 @@ uc_vm_execute_chunk(uc_vm_t *vm)
case I_CALL:
case I_QCALL:
uc_vm_insn_call(vm, insn);
frame = uc_vm_current_frame(vm);
chunk = frame->closure ? uc_vm_frame_chunk(frame) : NULL;
break;

case I_MCALL:
case I_QMCALL:
uc_vm_insn_mcall(vm, insn);
frame = uc_vm_current_frame(vm);
chunk = frame->closure ? uc_vm_frame_chunk(frame) : NULL;
break;

case I_RETURN:
Expand All @@ -2986,9 +2986,6 @@ uc_vm_execute_chunk(uc_vm_t *vm)

if (vm->callframes.count == 0)
return STATUS_OK;

frame = uc_vector_last(&vm->callframes);
chunk = uc_vm_frame_chunk(frame);
break;

case I_PRINT:
Expand Down Expand Up @@ -3039,10 +3036,6 @@ uc_vm_execute_chunk(uc_vm_t *vm)
/* no further callframe, report unhandled exception and terminate */
if (vm->callframes.count == 0 || vm->callframes.count <= caller)
return ERROR_RUNTIME;

/* resume execution in next remaining callframe */
frame = uc_vector_last(&vm->callframes);
chunk = uc_vm_frame_chunk(frame);
}
}

Expand Down

0 comments on commit c182101

Please sign in to comment.