Skip to content

Commit 9d24c11

Browse files
committed
Fix thread_profile_frames crashing due to uninitialized PC
ZJIT leaves cfp->pc uninitialized in many instances, and the conditions in thread_profile_frames() was outdated, leading sampling profilers to crash. Make sure to always pass a valid PC.
1 parent 5b5b5b3 commit 9d24c11

1 file changed

Lines changed: 6 additions & 10 deletions

File tree

vm_backtrace.c

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1729,7 +1729,6 @@ thread_profile_frames(rb_execution_context_t *ec, int start, int limit, VALUE *b
17291729
{
17301730
int i;
17311731
const rb_control_frame_t *cfp = ec->cfp, *end_cfp = RUBY_VM_END_CONTROL_FRAME(ec);
1732-
const rb_control_frame_t *top = cfp;
17331732
const rb_callable_method_entry_t *cme;
17341733

17351734
// If this function is called inside a thread after thread creation, but
@@ -1761,16 +1760,13 @@ thread_profile_frames(rb_execution_context_t *ec, int start, int limit, VALUE *b
17611760
}
17621761

17631762
if (lines) {
1764-
// The topmost frame may not have an updated PC because the JIT
1765-
// may not have set one. The JIT compiler will update the PC
1766-
// before entering a new function (so that `caller` will work),
1767-
// so only the topmost frame could possibly have an out of date PC
1768-
if (cfp == top && cfp->jit_return) {
1769-
lines[i] = 0;
1770-
}
1771-
else {
1772-
lines[i] = calc_lineno(cfp->iseq, cfp->pc);
1763+
VALUE *pc = cfp->pc;
1764+
VALUE *iseq_encoded = ISEQ_BODY(cfp->iseq)->iseq_encoded;
1765+
// JIT code may not set the PC, so use a valid one when out-of-range
1766+
if (cfp->pc < iseq_encoded || cfp->pc > iseq_encoded) {
1767+
pc = iseq_encoded;
17731768
}
1769+
lines[i] = calc_lineno(cfp->iseq, pc);
17741770
}
17751771

17761772
i++;

0 commit comments

Comments
 (0)