Branch: Tag:

2018-03-30

2018-03-30 16:06:39 by Arne Goedeke <el@laramies.com>

Interpreter: fixed handling of SAVE_LOCALS bitmask

Since the introduction of save_locals_bitmask, expendible_offset was
never set. Also since the handling of expendible_offset and
save_locals_bitmask were handled by the same case, the code was broken.

During pop entries handling of the save_locals bitmask could lead
to situations where locals above expendible_offset were 'copied' into
the trampoline frame. Those locals could have already been popped from
the stack by the RETURN_LOCAL opcode.

Also slightly refactored the code to not allocate more space for locals
than needed and removed some unnecessary casts.

This became visible and could lead to crashes when building for 32bit
on 64bit x86 machines.

1507:    DO_IF_NOT_REAL_DEBUG (    init_recovery (&new_catch_ctx->recovery, 0);    ); -  new_catch_ctx->save_expendible = frame_get_expendible(Pike_fp); +     JUMP_SET_TO_PC_AT_NEXT (addr);    new_catch_ctx->continue_reladdr = GET_JUMP()    /* We need to run the entry prologue... */
1521:    });    }    -  Pike_fp->expendible_offset = Pike_fp->num_locals; -  +     /* Need to adjust next_addr by sizeof(INT32) to skip past the jump    * address to the continue position after the catch block. */    addr = (PIKE_OPCODE_T *) ((INT32 *) addr + 1);
1588:       debug_malloc_touch_named (cc, "(3)");    UNSETJMP (cc->recovery); -  frame_set_expendible(Pike_fp, cc->save_expendible); +     move_svalue (Pike_sp++, &throw_value);    mark_free_svalue (&throw_value);    low_destruct_objects_to_destruct();
1784:    if(d_flag>3) do_gc(NULL, 0);    if(d_flag>4) do_debug();    ); -  if(Pike_fp->expendible_offset <= arg1) -  { +  if (!(Pike_fp->flags & PIKE_FRAME_SAVE_LOCALS)) {    pop_n_elems(Pike_sp-1 - (Pike_fp->locals + arg1)); -  DO_IF_DEBUG(Pike_fp->num_locals = arg1); -  }else{ +  } else {    push_svalue(Pike_fp->locals + arg1);    }    DO_DUMB_RETURN;
2824:    new_frame->args = args; \    new_frame->locals=Pike_sp-args; \    new_frame->save_sp_offset = 0; \ -  new_frame->expendible_offset = 0; \ +     new_frame->save_mark_sp = Pike_mark_sp; \    DO_IF_DEBUG(new_frame->num_args=0;new_frame->num_locals=0;); \    SET_PROG_COUNTER(addr); \
3057:    Pike_fp->num_locals = arg2;    });    - OPCODE1(F_PROTECT_STACK, "protect_stack", 0, { -  Pike_fp->expendible_offset = arg1; -  }); -  +    /* Save local variables according to bitmask. The high 16 bits of arg1    is an offset, the low 16 bits is a bitmask for that offset. See doc    for pike_frame.save_locals_bitmask. */