ruby-changes:49431
From: shyouhei <ko1@a...>
Date: Tue, 2 Jan 2018 15:59:31 +0900 (JST)
Subject: [ruby-changes:49431] shyouhei:r61569 (trunk): fix SEGV inspecting uninitialized objects
shyouhei 2018-01-02 15:42:05 +0900 (Tue, 02 Jan 2018) New Revision: 61569 https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=61569 Log: fix SEGV inspecting uninitialized objects obj_info() assumes the given object is alive. OTOH gc_writebarrier_incremental is called before or in middle of object initialization. Can casue SEGV. (lldb) run Process 48188 launched: './miniruby' (x86_64) Process 48188 stopped * thread #1: tid = 0x30fd53, 0x00000001000bf7a9 miniruby`rb_array_const_ptr(a=5251291222225483145) + 12 at ruby.h:2072, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT) frame #0: 0x00000001000bf7a9 miniruby`rb_array_const_ptr(a=5251291222225483145) + 12 at ruby.h:2072 2069 static inline const VALUE * 2070 rb_array_const_ptr(VALUE a) 2071 { -> 2072 return FIX_CONST_VALUE_PTR((RBASIC(a)->flags & RARRAY_EMBED_FLAG) ? 2073 RARRAY(a)->as.ary : RARRAY(a)->as.heap.ptr); 2074 } 2075 (lldb) bt * thread #1: tid = 0x30fd53, 0x00000001000bf7a9 miniruby`rb_array_const_ptr(a=5251291222225483145) + 12 at ruby.h:2072, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT) * frame #0: 0x00000001000bf7a9 miniruby`rb_array_const_ptr(a=5251291222225483145) + 12 at ruby.h:2072 frame #1: 0x00000001000bfaab miniruby`pathobj_path(pathobj=5251291222225483145) + 70 at vm_core.h:269 frame #2: 0x00000001000c25ff miniruby`rb_iseq_path(iseq=0x00000001025b71a8) + 32 at iseq.c:723 frame #3: 0x000000010009db09 miniruby`rb_raw_iseq_info(buff="0x00000001025b7158 [0 ] proc (Proc)", buff_size=256, iseq=0x00000001025b71a8) + 69 at gc.c:9274 frame #4: 0x000000010009e1d5 miniruby`rb_raw_obj_info(buff="0x00000001025b7158 [0 ] proc (Proc)", buff_size=256, obj=4334514520) + 1546 at gc.c:9351 frame #5: 0x000000010009e4d5 miniruby`obj_info(obj=4334514520) + 98 at gc.c:9429 frame #6: 0x0000000100096658 miniruby`gc_writebarrier_incremental(a=4334514520, b=4334514600, objspace=0x00000001007d3280) + 61 at gc.c:5963 frame #7: 0x00000001000968ca miniruby`rb_gc_writebarrier(a=4334514520, b=4334514600) + 127 at gc.c:6009 frame #8: 0x00000001001eabe0 miniruby`rb_obj_written(a=4334514520, oldv=52, b=4334514600, filename="/Users/urabe.shyouhei/data/src/pedantic/vm.c", line=821) + 72 at ruby.h:1472 frame #9: 0x00000001001eac2c miniruby`rb_obj_write(a=4334514520, slot=0x000000010259ff10, b=4334514600, filename="/Users/urabe.shyouhei/data/src/pedantic/vm.c", line=821) + 70 at ruby.h:1489 frame #10: 0x0000000100208b6f miniruby`vm_proc_create_from_captured(klass=4311027960, captured=0x0000000102500338, block_type=block_type_ifunc, is_from_method='\0', is_lambda='\x01') + 137 at vm.c:821 frame #11: 0x0000000100208e5c miniruby`rb_vm_make_proc_lambda(ec=0x00000001007d3548, captured=0x0000000102500338, klass=4311027960, is_lambda='\x01') + 134 at vm.c:892 frame #12: 0x000000010011f08e miniruby`proc_new(klass=4311027960, is_lambda='\x01') + 445 at proc.c:752 frame #13: 0x000000010011f110 miniruby`rb_block_lambda + 27 at proc.c:808 frame #14: 0x00000001001f24a7 miniruby`call_cfunc_0(func=(miniruby`rb_block_lambda at proc.c:807), recv=4310991600, argc=0, argv=0x0000000000000000) + 41 at vm_insnhelper.c:1729 frame #15: 0x00000001002033de miniruby`vm_call0_cfunc_with_frame(ec=0x00000001007d3548, calling=0x00007fff5fbfb080, ci=0x00007fff5fbfb070, cc=0x00007fff5fbfb0a0, argv=0x0000000000000000) + 370 at vm_eval.c:85 frame #16: 0x00000001002034d9 miniruby`vm_call0_cfunc(ec=0x00000001007d3548, calling=0x00007fff5fbfb080, ci=0x00007fff5fbfb070, cc=0x00007fff5fbfb0a0, argv=0x0000000000000000) + 59 at vm_eval.c:100 frame #17: 0x000000010020368f miniruby`vm_call0_body(ec=0x00000001007d3548, calling=0x00007fff5fbfb080, ci=0x00007fff5fbfb070, cc=0x00007fff5fbfb0a0, argv=0x0000000000000000) + 436 at vm_eval.c:131 frame #18: 0x000000010020326a miniruby`vm_call0(ec=0x00000001007d3548, recv=4310991600, id=2993, argc=0, argv=0x0000000000000000, me=0x0000000100f48110) + 142 at vm_eval.c:58 frame #19: 0x0000000100203c60 miniruby`rb_call0(ec=0x00000001007d3548, recv=4310991600, mid=2993, argc=0, argv=0x0000000000000000, scope=CALL_FCALL, self=4334514640) + 166 at vm_eval.c:296 frame #20: 0x0000000100204827 miniruby`rb_call(recv=4310991600, mid=2993, argc=0, argv=0x0000000000000000, scope=CALL_FCALL) + 84 at vm_eval.c:589 frame #21: 0x000000010020518b miniruby`rb_funcallv(recv=4310991600, mid=2993, argc=0, argv=0x0000000000000000) + 52 at vm_eval.c:815 frame #22: 0x000000010012242e miniruby`mlambda(method=0) + 45 at proc.c:2661 frame #23: 0x0000000100205bac miniruby`rb_iterate0(it_proc=(miniruby`mlambda at proc.c:2660), data1=0, ifunc=0x00000001025b71a8, ec=0x00000001007d3548) + 380 at vm_eval.c:1134 frame #24: 0x0000000100205d16 miniruby`rb_iterate(it_proc=(miniruby`mlambda at proc.c:2660), data1=0, bl_proc=(miniruby`bmcall at proc.c:2666), data2=4334514640) + 88 at vm_eval.c:1166 frame #25: 0x00000001001224c7 miniruby`method_to_proc(method=4334514640) + 43 at proc.c:2701 frame #26: 0x00000001001f24a7 miniruby`call_cfunc_0(func=(miniruby`method_to_proc at proc.c:2688), recv=4334514640, argc=0, argv=0x0000000102400568) + 41 at vm_insnhelper.c:1729 frame #27: 0x00000001001f2f87 miniruby`vm_call_cfunc_with_frame(ec=0x00000001007d3548, reg_cfp=0x0000000102500350, calling=0x00007fff5fbfc030, ci=0x0000000100f2ec70, cc=0x0000000102735718) + 386 at vm_insnhelper.c:1918 frame #28: 0x00000001001f30d6 miniruby`vm_call_cfunc(ec=0x00000001007d3548, reg_cfp=0x0000000102500350, calling=0x00007fff5fbfc030, ci=0x0000000100f2ec70, cc=0x0000000102735718) + 149 at vm_insnhelper.c:1934 frame #29: 0x00000001001f4319 miniruby`vm_call_method_each_type(ec=0x00000001007d3548, cfp=0x0000000102500350, calling=0x00007fff5fbfc030, ci=0x0000000100f2ec70, cc=0x0000000102735718) + 239 at vm_insnhelper.c:2232 frame #30: 0x00000001001f49a4 miniruby`vm_call_method(ec=0x00000001007d3548, cfp=0x0000000102500350, calling=0x00007fff5fbfc030, ci=0x0000000100f2ec70, cc=0x0000000102735718) + 117 at vm_insnhelper.c:2355 frame #31: 0x00000001001f4b7a miniruby`vm_call_general(ec=0x00000001007d3548, reg_cfp=0x0000000102500350, calling=0x00007fff5fbfc030, ci=0x0000000100f2ec70, cc=0x0000000102735718) + 59 at vm_insnhelper.c:2398 frame #32: 0x00000001001faf0e miniruby`vm_exec_core(ec=0x00000001007d3548, initial=0) + 8471 at insns.def:915 frame #33: 0x000000010020b75d miniruby`vm_exec(ec=0x00000001007d3548) + 230 at vm.c:1771 frame #34: 0x000000010020c3d1 miniruby`rb_iseq_eval(iseq=0x00000001007f8270) + 52 at vm.c:2008 frame #35: 0x00000001000caa4a miniruby`rb_load_internal0(ec=0x00000001007d3548, fname=4310799960, wrap=0) + 631 at load.c:611 frame #36: 0x00000001000cab36 miniruby`rb_load_internal(fname=4310799960, wrap=0) + 46 at load.c:642 frame #37: 0x00000001000cae1d miniruby`rb_f_load(argc=1, argv=0x00000001024004b8) + 217 at load.c:710 frame #38: 0x00000001001f247c miniruby`call_cfunc_m1(func=(miniruby`rb_f_load at load.c:695), recv=4311327440, argc=1, argv=0x00000001024004b8) + 47 at vm_insnhelper.c:1723 frame #39: 0x00000001001f2f87 miniruby`vm_call_cfunc_with_frame(ec=0x00000001007d3548, reg_cfp=0x00000001025003e0, calling=0x00007fff5fbfd3e0, ci=0x0000000102541070, cc=0x0000000100f9e918) + 386 at vm_insnhelper.c:1918 frame #40: 0x00000001001f30d6 miniruby`vm_call_cfunc(ec=0x00000001007d3548, reg_cfp=0x00000001025003e0, calling=0x00007fff5fbfd3e0, ci=0x0000000102541070, cc=0x0000000100f9e918) + 149 at vm_insnhelper.c:1934 frame #41: 0x00000001001f4319 miniruby`vm_call_method_each_type(ec=0x00000001007d3548, cfp=0x00000001025003e0, calling=0x00007fff5fbfd3e0, ci=0x0000000102541070, cc=0x0000000100f9e918) + 239 at vm_insnhelper.c:2232 frame #42: 0x00000001001f4a2c miniruby`vm_call_method(ec=0x00000001007d3548, cfp=0x00000001025003e0, calling=0x00007fff5fbfd3e0, ci=0x0000000102541070, cc=0x0000000100f9e918) + 253 at vm_insnhelper.c:2366 frame #43: 0x00000001001f4b7a miniruby`vm_call_general(ec=0x00000001007d3548, reg_cfp=0x00000001025003e0, calling=0x00007fff5fbfd3e0, ci=0x0000000102541070, cc=0x0000000100f9e918) + 59 at vm_insnhelper.c:2398 frame #44: 0x00000001001faf0e miniruby`vm_exec_core(ec=0x00000001007d3548, initial=0) + 8471 at insns.def:915 frame #45: 0x000000010020b75d miniruby`vm_exec(ec=0x00000001007d3548) + 230 at vm.c:1771 frame #46: 0x000000010020c40f miniruby`rb_iseq_eval_main(iseq=0x0000000100f21240) + 52 at vm.c:2019 frame #47: 0x000000010007c774 miniruby`ruby_exec_internal(n=0x0000000100f21240) + 297 at eval.c:246 frame #48: 0x000000010007c89a miniruby`ruby_exec_node(n=0x0000000100f21240) + 36 at eval.c:310 frame #49: 0x000000010007c86d miniruby`ruby_run_node(n=0x0000000100f21240) + 62 at eval.c:302 frame #50: 0x0000000100001399 miniruby`main(argc=9, argv=0x00007fff5fbfdae0) + 113 at main.c:42 frame #51: 0x00007fff88eda5ad libdyld.dylib`start + 1 (lldb) Modified files: trunk/gc.c Index: gc.c =================================================================== --- gc.c (revision 61568) +++ gc.c (revision 61569) @@ -5960,18 +5960,18 @@ NOINLINE(static void gc_writebarrier_inc https://github.com/ruby/ruby/blob/trunk/gc.c#L5960 static void gc_writebarrier_incremental(VALUE a, VALUE b, rb_objspace_t *objspace) { - gc_report(2, objspace, "gc_writebarrier_incremental: [LG] %s -> %s\n", obj_info(a), obj_info(b)); + gc_report(2, objspace, "gc_writebarrier_incremental: [LG] %p -> %s\n", (void *)a, obj_info(b)); if (RVALUE_BLACK_P(a)) { if (RVALUE_WHITE_P(b)) { if (!RVALUE_WB_UNPROTECTED(a)) { - gc_report(2, objspace, "gc_writebarrier_incremental: [IN] %s -> %s\n", obj_info(a), obj_info(b)); + gc_report(2, objspace, "gc_writebarrier_incremental: [IN] %p -> %s\n", (void *)a, obj_info(b)); gc_mark_from(objspace, b, a); } } else if (RVALUE_OLD_P(a) && !RVALUE_OLD_P(b)) { if (!RVALUE_WB_UNPROTECTED(b)) { - gc_report(1, objspace, "gc_writebarrier_incremental: [GN] %s -> %s\n", obj_info(a), obj_info(b)); + gc_report(1, objspace, "gc_writebarrier_incremental: [GN] %p -> %s\n", (void *)a, obj_info(b)); RVALUE_AGE_SET_OLD(objspace, b); if (RVALUE_BLACK_P(b)) { @@ -5979,7 +5979,7 @@ gc_writebarrier_incremental(VALUE a, VAL https://github.com/ruby/ruby/blob/trunk/gc.c#L5979 } } else { - gc_report(1, objspace, "gc_writebarrier_incremental: [LL] %s -> %s\n", obj_info(a), obj_info(b)); + gc_report(1, objspace, "gc_writebarrier_incremental: [LL] %p -> %s\n", (void *)a, obj_info(b)); gc_remember_unprotected(objspace, b); } } -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/