Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Segmentation fault on sclass with block #3214

Closed
ksss opened this issue Sep 22, 2016 · 0 comments
Closed

Segmentation fault on sclass with block #3214

ksss opened this issue Sep 22, 2016 · 0 comments

Comments

@ksss
Copy link
Contributor

ksss commented Sep 22, 2016

t.rb

module A
  def self.sclass_with_block
    class << self
      yield
    end
  end
end

p A.sclass_with_block { 123 }
$ ruby t.rb
123

$ mruby t.rb
[1]    32880 segmentation fault  mruby t.rb

This behavior was defined on ruby/spec.

https://github.com/ruby/spec/blob/d05fabfe0ba3774710d912d2802d6d235c1ed8ae/language/class_spec.rb#L290

The reasons is that outer class is recursive.

lldb backtrace.

$ lldb mruby
(lldb) run t.rb
Process 33414 launched: 'bin/mruby' (x86_64)
Process 33414 stopped
* thread #1: tid = 0x4b3514, 0x00000001000363f8 mruby`sym_validate_len(mrb=<unavailable>, len=<unavailable>) + 8 at symbol.c:41, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=2, address=0x7fff5f3ffff8)
    frame #0: 0x00000001000363f8 mruby`sym_validate_len(mrb=<unavailable>, len=<unavailable>) + 8 at symbol.c:41
   38
   39   static void
   40   sym_validate_len(mrb_state *mrb, size_t len)
-> 41   {
   42     if (len >= RITE_LV_NULL_MARK) {
   43       mrb_raise(mrb, E_ARGUMENT_ERROR, "symbol length too long");
   44     }
(lldb) bt
...
    frame #32748: 0x000000010000b82a mruby`mrb_class_path(mrb=0x0000000100202ad0, c=0x00000001008063e0) + 218 at class.c:1512
    frame #32749: 0x000000010000b82a mruby`mrb_class_path(mrb=0x0000000100202ad0, c=0x00000001008063e0) + 218 at class.c:1512
    frame #32750: 0x000000010000b82a mruby`mrb_class_path(mrb=0x0000000100202ad0, c=0x00000001008063e0) + 218 at class.c:1512
    frame #32751: 0x000000010000b82a mruby`mrb_class_path(mrb=0x0000000100202ad0, c=0x00000001008063e0) + 218 at class.c:1512
    frame #32752: 0x000000010000b82a mruby`mrb_class_path(mrb=0x0000000100202ad0, c=0x00000001008063e0) + 218 at class.c:1512
    frame #32753: 0x000000010000b82a mruby`mrb_class_path(mrb=0x0000000100202ad0, c=0x00000001008063e0) + 218 at class.c:1512
    frame #32754: 0x000000010000b82a mruby`mrb_class_path(mrb=0x0000000100202ad0, c=0x00000001008063e0) + 218 at class.c:1512
    frame #32755: 0x000000010000b82a mruby`mrb_class_path(mrb=0x0000000100202ad0, c=0x00000001008063e0) + 218 at class.c:1512
    frame #32756: 0x000000010000b82a mruby`mrb_class_path(mrb=0x0000000100202ad0, c=0x00000001008063e0) + 218 at class.c:1512
    frame #32757: 0x000000010000ba3d mruby`mrb_class_name(mrb=0x0000000100202ad0, c=0x00000001008063e0) + 29 at class.c:1549
    frame #32758: 0x00000001000061ea mruby`output_backtrace_i(mrb=0x0000000100202ad0, loc_raw=0x00007fff5fbff3a0, data=0x00007fff5fbff408) + 106 at backtrace.c:170
    frame #32759: 0x0000000100005db1 mruby`each_backtrace(mrb=0x0000000100202ad0, ciidx=2, pc0=0x00000001002348f0, func=(mruby`output_backtrace_i at backtrace.c:161), data=0x00007fff5fbff408) + 529 at backtrace.c:150
    frame #32760: 0x00000001000059fc mruby`output_backtrace(mrb=0x0000000100202ad0, ciidx=2, pc0=0x00000001002348f0, func=(mruby`print_backtrace_i at backtrace.c:47), data=0x00007fff5fbff4f8) + 76 at backtrace.c:181
    frame #32761: 0x000000010000554c mruby`exc_output_backtrace(mrb=0x0000000100202ad0, exc=0x0000000100805c30, func=(mruby`print_backtrace_i at backtrace.c:47), stream=0x00007fff5fbff4f8) + 252 at backtrace.c:197
    frame #32762: 0x000000010000518b mruby`mrb_print_backtrace(mrb=0x0000000100202ad0) + 315 at backtrace.c:278
    frame #32763: 0x0000000100028935 mruby`mrb_print_error(mrb=0x0000000100202ad0) + 21 at print.c:33
    frame #32764: 0x00000001000012b9 mruby`main(argc=2, argv=0x00007fff5fbff6f0) + 1081 at mruby.c:238
    frame #32765: 0x00007fff9b92e5ad libdyld.dylib`start + 1

Outer class was set on here.

mruby/src/class.c

Lines 1135 to 1136 in 77d004e

mrb_obj_iv_set(mrb, (struct RObject*)obj->c, mrb_intern_lit(mrb, "__outer__"),
mrb_obj_value(mrb->c->ci->target_class));

When obj->c == mrb->c->ci->target_class,

Recursive calling happened on the below line.

mruby/src/class.c

Line 1512 in 77d004e

mrb_value base = mrb_class_path(mrb, outer);


I applied this patch.
It didn't raise segv.
But behavior was different with CRuby.

diff --git a/src/class.c b/src/class.c
index 47a6c84..40faffb 100644
--- a/src/class.c
+++ b/src/class.c
@@ -1131,7 +1131,7 @@ mrb_singleton_class(mrb_state *mrb, mrb_value v)
   }
   obj = mrb_basic_ptr(v);
   prepare_singleton_class(mrb, obj);
-  if (mrb->c && mrb->c->ci && mrb->c->ci->target_class) {
+  if (mrb->c && mrb->c->ci && mrb->c->ci->target_class && obj->c != mrb->c->ci->target_class) {
     mrb_obj_iv_set(mrb, (struct RObject*)obj->c, mrb_intern_lit(mrb, "__outer__"),
                    mrb_obj_value(mrb->c->ci->target_class));
   }
$ mruby t.rb
trace:
    [2] t.rb:6
    [1] t.rb:5:in A#sclass_with_block
    [0] t.rb:11
LocalJumpError: unexpected yield

https://github.com/mruby/mruby/blame/77d004e8352dab0bcb0c9bd6826f20a5e0185e3e/src/vm.c#L1737

@matz matz closed this as completed in 0b8d8dd Nov 4, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant