Actions
Bug #12430
closedSegfault in irb when improperly using coerce in combination with method_missing
Bug #12430: Segfault in irb when improperly using coerce in combination with method_missing
Description
Don't ask how or why I wrote this code, but suppose you have a class like this:
class BrokenNumber def initialize(num) @num = num end def method_missing(m, *a, &b) @num.send(m, *a, &b) end def coerce(other) [self, self] end end Then you require this code in IRB, and you create a new instance (x) and you then call 2+x.
The first call will raise a SystemStackError. The second will cause a segmentation fault.
>> require "./broken" => true >> x = BrokenNumber.new(2) => #<BrokenNumber:0x007f8b5a84c190 @num=2> >> 2 + x SystemStackError: stack level too deep from /Users/gtb/broken.rb:7:in `+' from /Users/gtb/broken.rb:7:in `method_missing' from /Users/gtb/broken.rb:7:in `+' from /Users/gtb/broken.rb:7:in `method_missing' from /Users/gtb/broken.rb:7:in `+' from /Users/gtb/broken.rb:7:in `method_missing' from /Users/gtb/broken.rb:7:in `+' from /Users/gtb/broken.rb:7:in `method_missing' from /Users/gtb/broken.rb:7:in `+' from /Users/gtb/broken.rb:7:in `method_missing' from /Users/gtb/broken.rb:7:in `+' from /Users/gtb/broken.rb:7:in `method_missing' from /Users/gtb/broken.rb:7:in `+' from /Users/gtb/broken.rb:7:in `method_missing' from /Users/gtb/broken.rb:7:in `+' from /Users/gtb/broken.rb:7:in `method_missing' ... 7559 levels... from /Users/gtb/broken.rb:7:in `method_missing' from /Users/gtb/broken.rb:7:in `+' from /Users/gtb/broken.rb:7:in `method_missing' from /Users/gtb/broken.rb:7:in `+' from /Users/gtb/broken.rb:7:in `method_missing' from /Users/gtb/broken.rb:7:in `+' from /Users/gtb/broken.rb:7:in `method_missing' from /Users/gtb/broken.rb:7:in `+' from /Users/gtb/broken.rb:7:in `method_missing' from /Users/gtb/broken.rb:7:in `+' from /Users/gtb/broken.rb:7:in `method_missing' from /Users/gtb/broken.rb:7:in `+' from /Users/gtb/broken.rb:7:in `method_missing' from (irb):3:in `+' from (irb):3 from /Users/gtb/.rubies/ruby-2.3.1/bin/irb:11:in `<main>' >> 2 + x Segmentation fault: 11 MacBook-Pro:~ gtb$ ruby -v ruby 2.3.1p112 (2016-04-26 revision 54768) [x86_64-darwin15] I've asked multiple people to confirm this and they've reproduced the error. I have no clue how to debug it, but thought it may be worth mentioning... even though it's a strange corner case and invalid code.
Updated by sandal (Gregory Brown) over 9 years ago
- ruby -v set to ruby 2.3.1p112
Updated by jeremyevans0 (Jeremy Evans) over 6 years ago
- Status changed from Open to Closed
I don't think this is a bug, the SystemStackError is expected. In some cases, Ruby doesn't catch the stack overflow and you end up with a segfault.
The reason for the behavior:
x = BrokenNumber.new(2) # original expression 2 + x # Integer#+ calls (via rb_num_coerce_bin->do_coerce): x.coerce(2) # x.coerce(2) returns: [x, x] # Integer#+ calls (via rb_num_coerce_bin): x + x # BrokenNumber#+ not defined, so calls: x.method_missing(:+, x) # BrokenNumber#method_missing calls: 2 + x # the original expression, so a loop Actions