Fix stack-use-after-scope in gen_direct_jump()

ASAN can catch these type of things for us, but the scraper can't
handle ASAN :/.

To be more resilient to refactoring, extend the lifetime of
`generic_ctx` in branch_stub_hit() too.
This commit is contained in:
Alan Wu 2021-04-08 17:55:31 -04:00
parent 032b2ecf4b
commit e81d1f4ae3

View File

@ -487,6 +487,7 @@ static uint8_t *
branch_stub_hit(const uint32_t branch_idx, const uint32_t target_idx, rb_execution_context_t* ec) branch_stub_hit(const uint32_t branch_idx, const uint32_t target_idx, rb_execution_context_t* ec)
{ {
uint8_t* dst_addr; uint8_t* dst_addr;
ctx_t generic_ctx;
// Stop other ractors since we are going to patch machine code. // Stop other ractors since we are going to patch machine code.
// This is how the GC does it. // This is how the GC does it.
@ -529,12 +530,12 @@ branch_stub_hit(const uint32_t branch_idx, const uint32_t target_idx, rb_executi
// If this block hasn't yet been compiled // If this block hasn't yet been compiled
if (!p_block) { if (!p_block) {
// Limit the number of block versions // Limit the number of block versions
ctx_t generic_ctx = DEFAULT_CTX;
generic_ctx.stack_size = target_ctx->stack_size;
generic_ctx.sp_offset = target_ctx->sp_offset;
if (target_ctx->chain_depth == 0) { // guard chains implement limits individually if (target_ctx->chain_depth == 0) { // guard chains implement limits individually
if (get_num_versions(target) >= MAX_VERSIONS - 1) { if (get_num_versions(target) >= MAX_VERSIONS - 1) {
//fprintf(stderr, "version limit hit in branch_stub_hit\n"); //fprintf(stderr, "version limit hit in branch_stub_hit\n");
generic_ctx = DEFAULT_CTX;
generic_ctx.stack_size = target_ctx->stack_size;
generic_ctx.sp_offset = target_ctx->sp_offset;
target_ctx = &generic_ctx; target_ctx = &generic_ctx;
} }
} }
@ -697,6 +698,7 @@ void gen_direct_jump(
{ {
RUBY_ASSERT(target0.iseq != NULL); RUBY_ASSERT(target0.iseq != NULL);
RUBY_ASSERT(num_branches < MAX_BRANCHES); RUBY_ASSERT(num_branches < MAX_BRANCHES);
ctx_t generic_ctx;
uint32_t branch_idx = num_branches++; uint32_t branch_idx = num_branches++;
// Branch targets or stub adddress // Branch targets or stub adddress
@ -726,12 +728,12 @@ void gen_direct_jump(
else else
{ {
// Limit the number of block versions // Limit the number of block versions
ctx_t generic_ctx = DEFAULT_CTX;
generic_ctx.stack_size = ctx->stack_size;
generic_ctx.sp_offset = ctx->sp_offset;
if (get_num_versions(target0) >= MAX_VERSIONS - 1) if (get_num_versions(target0) >= MAX_VERSIONS - 1)
{ {
//fprintf(stderr, "version limit hit in gen_direct_jump\n"); //fprintf(stderr, "version limit hit in gen_direct_jump\n");
generic_ctx = DEFAULT_CTX;
generic_ctx.stack_size = ctx->stack_size;
generic_ctx.sp_offset = ctx->sp_offset;
ctx = &generic_ctx; ctx = &generic_ctx;
} }
@ -768,8 +770,7 @@ void defer_compilation(
//fprintf(stderr, "defer compilation at (%p, %d) depth=%d\n", block->blockid.iseq, insn_idx, cur_ctx->chain_depth); //fprintf(stderr, "defer compilation at (%p, %d) depth=%d\n", block->blockid.iseq, insn_idx, cur_ctx->chain_depth);
if (cur_ctx->chain_depth != 0) { if (cur_ctx->chain_depth != 0) {
rb_backtrace(); rb_bug("double defer");
exit(1);
} }
ctx_t next_ctx = *cur_ctx; ctx_t next_ctx = *cur_ctx;