mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
fix tracepoint + backtrace SEGV
PC modification in gc_event_hook_body was careless. There are (so to say) abnormal iseqs stored in the cfp. We have to check sanity before we touch the PC. This has not been fixed because there was no way to (ab)use the setup from pure-Ruby. However by using our official C APIs it is possible to touch such frame(s), resulting in SEGV. Fixes [Bug #14834].
This commit is contained in:
parent
d2f8e03f34
commit
5d33f78716
5 changed files with 68 additions and 2 deletions
35
ext/-test-/bug-14834/bug-14384.c
Normal file
35
ext/-test-/bug-14834/bug-14384.c
Normal file
|
@ -0,0 +1,35 @@
|
|||
#include <ruby/ruby.h>
|
||||
#include <ruby/debug.h>
|
||||
|
||||
static NOINLINE(VALUE f(VALUE));
|
||||
static NOINLINE(void g(VALUE, void*));
|
||||
extern NOINLINE(void Init_bug_14384(void));
|
||||
|
||||
void
|
||||
Init_bug_14834(void)
|
||||
{
|
||||
VALUE q = rb_define_module("Bug");
|
||||
rb_define_module_function(q, "bug_14834", f, 0);
|
||||
}
|
||||
|
||||
VALUE
|
||||
f(VALUE q)
|
||||
{
|
||||
int w[] = { 0, 1024 };
|
||||
VALUE e = rb_tracepoint_new(Qnil, RUBY_INTERNAL_EVENT_NEWOBJ, g, w);
|
||||
|
||||
rb_tracepoint_enable(e);
|
||||
return rb_ensure(rb_yield, q, rb_tracepoint_disable, e);
|
||||
}
|
||||
|
||||
void
|
||||
g(MAYBE_UNUSED(VALUE q), void* w)
|
||||
{
|
||||
const int *e = (const int *)w;
|
||||
const int r = *e++;
|
||||
const int t = *e++;
|
||||
VALUE y[t];
|
||||
int u[t];
|
||||
|
||||
rb_profile_frames(r, t, y, u);
|
||||
}
|
14
ext/-test-/bug-14834/depend
Normal file
14
ext/-test-/bug-14834/depend
Normal file
|
@ -0,0 +1,14 @@
|
|||
# AUTOGENERATED DEPENDENCIES START
|
||||
bug-14384.o: $(RUBY_EXTCONF_H)
|
||||
bug-14384.o: $(arch_hdrdir)/ruby/config.h
|
||||
bug-14384.o: $(hdrdir)/ruby/assert.h
|
||||
bug-14384.o: $(hdrdir)/ruby/backward.h
|
||||
bug-14384.o: $(hdrdir)/ruby/debug.h
|
||||
bug-14384.o: $(hdrdir)/ruby/defines.h
|
||||
bug-14384.o: $(hdrdir)/ruby/intern.h
|
||||
bug-14384.o: $(hdrdir)/ruby/missing.h
|
||||
bug-14384.o: $(hdrdir)/ruby/ruby.h
|
||||
bug-14384.o: $(hdrdir)/ruby/st.h
|
||||
bug-14384.o: $(hdrdir)/ruby/subst.h
|
||||
bug-14384.o: bug-14384.c
|
||||
# AUTOGENERATED DEPENDENCIES END
|
2
ext/-test-/bug-14834/extconf.rb
Normal file
2
ext/-test-/bug-14834/extconf.rb
Normal file
|
@ -0,0 +1,2 @@
|
|||
# frozen_string_literal: true
|
||||
create_makefile("-test-/bug_14834")
|
7
gc.c
7
gc.c
|
@ -1925,8 +1925,11 @@ rb_objspace_set_event_hook(const rb_event_flag_t event)
|
|||
static void
|
||||
gc_event_hook_body(rb_execution_context_t *ec, rb_objspace_t *objspace, const rb_event_flag_t event, VALUE data)
|
||||
{
|
||||
/* increment PC because source line is calculated with PC-1 */
|
||||
const VALUE *pc = ec->cfp->pc++;
|
||||
const VALUE *pc = ec->cfp->pc;
|
||||
if (VM_FRAME_RUBYFRAME_P(ec->cfp)) {
|
||||
/* increment PC because source line is calculated with PC-1 */
|
||||
ec->cfp->pc++;
|
||||
}
|
||||
EXEC_EVENT_HOOK(ec, event, ec->cfp->self, 0, 0, 0, data);
|
||||
ec->cfp->pc = pc;
|
||||
}
|
||||
|
|
12
test/-ext-/test_bug-14834.rb
Normal file
12
test/-ext-/test_bug-14834.rb
Normal file
|
@ -0,0 +1,12 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Test_BUG_14834 < Test::Unit::TestCase
|
||||
def test
|
||||
assert_ruby_status [], <<~'end;', '[ruby-core:87449] [Bug #14834]'
|
||||
require '-test-/bug_14834'
|
||||
Bug.bug_14834 do
|
||||
[123].group_by {}
|
||||
end
|
||||
end;
|
||||
end
|
||||
end
|
Loading…
Add table
Reference in a new issue