Issue #14834 has been updated by kivikakk (Ashe Connor).


It's also worth noting:

* is the increment of `pc` with `ec->cfp->pc++` correct? What if the instruction is multiple values wide?
* there are similar `pc` increment/decrement pairs around `EXEC_EVENT_HOOK` calls in `vm_trace`. Do we need to address these too?

Ping @tenderlovemaking as he helped me with this.

----------------------------------------
Bug #14834: rb_profile_frames SEGV when PC adjusted on IFUNC
https://bugs.ruby-lang.org/issues/14834#change-72442

* Author: kivikakk (Ashe Connor)
* Status: Open
* Priority: Normal
* Assignee: 
* Target version: 
* ruby -v: ruby 2.6.0dev (2018-06-08 trunk 63606) [x86_64-linux]
* Backport: 2.3: UNKNOWN, 2.4: UNKNOWN, 2.5: UNKNOWN
----------------------------------------
Since r62052, we increment `ec->cfp->pc` by one pointer width (e.g. 8 bytes) in `gc_event_hook_body` around the `EXEC_EVENT_HOOK` call.

This becomes a problem when the hook is on an IFUNC: in this case, `pc == 0x0`, meaning we increment it to a non-zero value during that call.

`rb_profile_frames` uses the following check to determine if frame info should be recorded:

~~~ c
	if (cfp->iseq && cfp->pc) {
~~~


The example here is [`stackprof`](https://github.com/tmm1/stackprof/blob/58d65ffa801ed27f013d573148783694526c7426/ext/stackprof/stackprof.c#L486), which calls `rb_profile_frames` in a gc event hook. This will segfault currently, as the above check will pass.

`calc_lineno` then attempts to calculate the line number:

~~~ c
        size_t pos = (size_t)(pc - iseq->body->iseq_encoded);
~~~

This fails for a variety of reasons: `iseq_encoded` isn't valid because `iseq` isn't an `rb_iseq_t` underneath, producing an essentially random value, and `pc` is 0x8, so we underflow and eventually cause an overrun in `succ_index_lookup` with a huge `pos` argument.

We instead only adjust PC if it appears to be a valid pointer in the first place.

---Files--------------------------------
pc-treatment.diff (777 Bytes)


-- 
https://bugs.ruby-lang.org/

Unsubscribe: <mailto:ruby-core-request / ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>