Forked from JoshCheek/accidentally_renames_instance_variables.rb
Created
March 24, 2018 18:51
-
-
Save treble37/76da81e1b312389f2275995a1e5a0ea8 to your computer and use it in GitHub Desktop.
Example of the kinds of issues you can hit when you directly mess with memory
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'fiddle' | |
public def class=(new_class) | |
obj_ptr = Fiddle::Pointer.new 2*self.object_id | |
klass_ptr = Fiddle::Pointer.new 2*new_class.object_id | |
obj_ptr[8, 8] = klass_ptr.ref[0, 8] | |
end | |
class A | |
attr_accessor :a, :b, :c | |
end | |
class B | |
attr_accessor :a, :b, :c | |
end | |
# The optimization is to store them inside the object instead of allocating the ivar hash | |
# which ivar corresponds to which location is based on the order they are set in. | |
# Since we set B's ivars in a different order, their values get swapped. | |
a = A.new | |
a.a = 'a' | |
a.b = 'b' | |
a.c = 'c' | |
b = B.new | |
b.c = 'c' | |
b.a = 'a' | |
b.b = 'b' | |
a # => #<A:0x00007fc62797e2b8 @a="a", @b="b", @c="c"> | |
a.class = B | |
a # => #<B:0x00007fc62797e2b8 @c="a", @a="b", @b="c"> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'fiddle' | |
public def class=(new_class) | |
obj_ptr = Fiddle::Pointer.new 2*self.object_id | |
klass_ptr = Fiddle::Pointer.new 2*new_class.object_id | |
obj_ptr[8, 8] = klass_ptr.ref[0, 8] | |
end | |
class A | |
attr_accessor :a, :b, :c, :d | |
end | |
# Instance vars get lost when there are 3 or fewer, due to an optimization | |
a = A.new | |
a.a = a.b = a.c = :whatever | |
a # => #<A:0x00007fd3d68d6880 @c=:whatever, @b=:whatever, @a=:whatever> | |
a.class = Object | |
a # => #<Object:0x00007fd3d68d6880> | |
# Add a fourth ivar and Ruby stores them in the hash table of instance variables | |
a = A.new | |
a.a = a.b = a.c = a.d = :whatever | |
a # => #<A:0x00007fd3d68d62b8 @c=:whatever, @b=:whatever, @a=:whatever, @d=:whatever> | |
a.class = Object | |
a # => #<Object:0x00007fd3d68d62b8 @c=:whatever, @b=:whatever, @a=:whatever, @d=:whatever> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'fiddle' | |
public def class=(new_class) | |
obj_ptr = Fiddle::Pointer.new 2*self.object_id | |
klass_ptr = Fiddle::Pointer.new 2*new_class.object_id | |
obj_ptr[8, 8] = klass_ptr.ref[0, 8] | |
end | |
# here, we set the class to a non-class value. When we call a method on it, it | |
# tries to treat "false" as if it was a class, but it isn't. This causes invalid | |
# memory access, which causes a segmentation fault | |
o = Object.new | |
o.class = false | |
o.inspect | |
# !> program.rb:13: [BUG] Segmentation fault at 0x0000000000000018 | |
# !> ruby 2.5.0p0 (2017-12-25 revision 61468) [x86_64-darwin17] | |
# !> | |
# !> -- Crash Report log information -------------------------------------------- | |
# !> See Crash Report log file under the one of following: | |
# !> * ~/Library/Logs/DiagnosticReports | |
# !> * /Library/Logs/DiagnosticReports | |
# !> for more details. | |
# !> Don't forget to include the above Crash Report log file in bug reports. | |
# !> | |
# !> -- Control frame information ----------------------------------------------- | |
# !> c:0002 p:0046 s:0008 E:000f28 EVAL program.rb:13 [FINISH] | |
# !> c:0001 p:0000 s:0003 E:000470 (none) [FINISH] | |
# !> | |
# !> -- Ruby level backtrace information ---------------------------------------- | |
# !> program.rb:13:in `<main>' | |
# !> | |
# !> -- Machine register context ------------------------------------------------ | |
# !> rax: 0x0000000000000000 rbx: 0x0000000000000000 rcx: 0x00000000000002a1 | |
# !> rdx: 0x00007ffeef173bc0 rdi: 0x0000000000000000 rsi: 0x0000000000000000 | |
# !> rbp: 0x00007ffeef173bb0 rsp: 0x00007ffeef173b70 r8: 0x00007fa4140f4600 | |
# !> r9: 0x000000010112b0a0 r10: 0x00007fa4150571f0 r11: 0x00000000000000c0 | |
# !> r12: 0x0000000000000000 r13: 0x0000000000000aa1 r14: 0x0000000000000aa1 | |
# !> r15: 0x0000000000000aa1 rip: 0x0000000100c5d335 rfl: 0x0000000000010202 | |
# !> | |
# !> -- C level backtrace information ------------------------------------------- | |
# !> 0 ruby 0x0000000100c77db7 rb_vm_bugreport + 135 | |
# !> 1 ruby 0x0000000100afced8 rb_bug_context + 472 | |
# !> 2 ruby 0x0000000100bec3e1 sigsegv + 81 | |
# !> 3 libsystem_platform.dylib 0x00007fff73f70f5a _sigtramp + 26 | |
# !> 4 ruby 0x0000000100c5d335 method_entry_get + 261 | |
# !> 5 ruby 0x0000000100c5d3cb rb_callable_method_entry + 27 | |
# !> 6 ruby 0x0000000100c549bb vm_exec_core + 12123 | |
# !> 7 ruby 0x0000000100c65b6e vm_exec + 142 | |
# !> 8 ruby 0x0000000100b069b1 ruby_exec_internal + 177 | |
# !> 9 ruby 0x0000000100b068a8 ruby_run_node + 56 | |
# !> 10 ruby 0x0000000100a8c0ff main + 79 | |
# !> | |
# !> -- Other runtime information ----------------------------------------------- | |
# !> | |
# !> * Loaded script: program.rb | |
# !> | |
# !> * Loaded features: | |
# !> | |
# !> 0 enumerator.so | |
# !> 1 thread.rb | |
# !> 2 rational.so | |
# !> 3 complex.so | |
# !> 4 /Users/xjxc322/.rubies/ruby-2.5.0/lib/ruby/2.5.0/x86_64-darwin17/enc/encdb.bundle | |
# !> 5 /Users/xjxc322/.rubies/ruby-2.5.0/lib/ruby/2.5.0/x86_64-darwin17/enc/trans/transdb.bundle | |
# !> 6 /Users/xjxc322/.rubies/ruby-2.5.0/lib/ruby/2.5.0/x86_64-darwin17/rbconfig.rb | |
# !> 7 /Users/xjxc322/.rubies/ruby-2.5.0/lib/ruby/2.5.0/rubygems/compatibility.rb | |
# !> 8 /Users/xjxc322/.rubies/ruby-2.5.0/lib/ruby/2.5.0/rubygems/defaults.rb | |
# !> 9 /Users/xjxc322/.rubies/ruby-2.5.0/lib/ruby/2.5.0/rubygems/deprecate.rb | |
# !> 10 /Users/xjxc322/.rubies/ruby-2.5.0/lib/ruby/2.5.0/rubygems/errors.rb | |
# !> 11 /Users/xjxc322/.rubies/ruby-2.5.0/lib/ruby/2.5.0/rubygems/version.rb | |
# !> 12 /Users/xjxc322/.rubies/ruby-2.5.0/lib/ruby/2.5.0/rubygems/requirement.rb | |
# !> 13 /Users/xjxc322/.rubies/ruby-2.5.0/lib/ruby/2.5.0/rubygems/platform.rb | |
# !> 14 /Users/xjxc322/.rubies/ruby-2.5.0/lib/ruby/2.5.0/rubygems/basic_specification.rb | |
# !> 15 /Users/xjxc322/.rubies/ruby-2.5.0/lib/ruby/2.5.0/rubygems/stub_specification.rb | |
# !> 16 /Users/xjxc322/.rubies/ruby-2.5.0/lib/ruby/2.5.0/rubygems/util/list.rb | |
# !> 17 /Users/xjxc322/.rubies/ruby-2.5.0/lib/ruby/2.5.0/x86_64-darwin17/stringio.bundle | |
# !> 18 /Users/xjxc322/.rubies/ruby-2.5.0/lib/ruby/2.5.0/rubygems/specification.rb | |
# !> 19 /Users/xjxc322/.rubies/ruby-2.5.0/lib/ruby/2.5.0/rubygems/exceptions.rb | |
# !> 20 /Users/xjxc322/.rubies/ruby-2.5.0/lib/ruby/2.5.0/rubygems/dependency.rb | |
# !> 21 /Users/xjxc322/.rubies/ruby-2.5.0/lib/ruby/2.5.0/rubygems/core_ext/kernel_gem.rb | |
# !> 22 /Users/xjxc322/.rubies/ruby-2.5.0/lib/ruby/2.5.0/monitor.rb | |
# !> 23 /Users/xjxc322/.rubies/ruby-2.5.0/lib/ruby/2.5.0/rubygems/core_ext/kernel_require.rb | |
# !> 24 /Users/xjxc322/.rubies/ruby-2.5.0/lib/ruby/2.5.0/rubygems.rb | |
# !> 25 /Users/xjxc322/.rubies/ruby-2.5.0/lib/ruby/2.5.0/rubygems/path_support.rb | |
# !> 26 /Users/xjxc322/.rubies/ruby-2.5.0/lib/ruby/gems/2.5.0/gems/did_you_mean-1.2.0/lib/did_you_mean/version.rb | |
# !> 27 /Users/xjxc322/.rubies/ruby-2.5.0/lib/ruby/gems/2.5.0/gems/did_you_mean-1.2.0/lib/did_you_mean/core_ext/name_error.rb | |
# !> 28 /Users/xjxc322/.rubies/ruby-2.5.0/lib/ruby/gems/2.5.0/gems/did_you_mean-1.2.0/lib/did_you_mean/levenshtein.rb | |
# !> 29 /Users/xjxc322/.rubies/ruby-2.5.0/lib/ruby/gems/2.5.0/gems/did_you_mean-1.2.0/lib/did_you_mean/jaro_winkler.rb | |
# !> 30 /Users/xjxc322/.rubies/ruby-2.5.0/lib/ruby/gems/2.5.0/gems/did_you_mean-1.2.0/lib/did_you_mean/spell_checker.rb | |
# !> 31 /Users/xjxc322/.rubies/ruby-2.5.0/lib/ruby/2.5.0/delegate.rb | |
# !> 32 /Users/xjxc322/.rubies/ruby-2.5.0/lib/ruby/gems/2.5.0/gems/did_you_mean-1.2.0/lib/did_you_mean/spell_checkers/name_error_checkers/class_name_checker.rb | |
# !> 33 /Users/xjxc322/.rubies/ruby-2.5.0/lib/ruby/gems/2.5.0/gems/did_you_mean-1.2.0/lib/did_you_mean/spell_checkers/name_error_checkers/variable_name_checker.rb | |
# !> 34 /Users/xjxc322/.rubies/ruby-2.5.0/lib/ruby/gems/2.5.0/gems/did_you_mean-1.2.0/lib/did_you_mean/spell_checkers/name_error_checkers.rb | |
# !> 35 /Users/xjxc322/.rubies/ruby-2.5.0/lib/ruby/gems/2.5.0/gems/did_you_mean-1.2.0/lib/did_you_mean/spell_checkers/method_name_checker.rb | |
# !> 36 /Users/xjxc322/.rubies/ruby-2.5.0/lib/ruby/gems/2.5.0/gems/did_you_mean-1.2.0/lib/did_you_mean/spell_checkers/key_error_checker.rb | |
# !> 37 /Users/xjxc322/.rubies/ruby-2.5.0/lib/ruby/gems/2.5.0/gems/did_you_mean-1.2.0/lib/did_you_mean/spell_checkers/null_checker.rb | |
# !> 38 /Users/xjxc322/.rubies/ruby-2.5.0/lib/ruby/gems/2.5.0/gems/did_you_mean-1.2.0/lib/did_you_mean/formatters/plain_formatter.rb | |
# !> 39 /Users/xjxc322/.rubies/ruby-2.5.0/lib/ruby/gems/2.5.0/gems/did_you_mean-1.2.0/lib/did_you_mean.rb | |
# !> 40 /Users/xjxc322/.gem/ruby/2.5.0/gems/seeing_is_believing-3.4.0/lib/seeing_is_believing/safe.rb | |
# !> 41 /Users/xjxc322/.gem/ruby/2.5.0/gems/seeing_is_believing-3.4.0/lib/seeing_is_believing/version.rb | |
# !> 42 /Users/xjxc322/.gem/ruby/2.5.0/gems/seeing_is_believing-3.4.0/lib/seeing_is_believing/hash_struct.rb | |
# !> 43 /Users/xjxc322/.gem/ruby/2.5.0/gems/seeing_is_believing-3.4.0/lib/seeing_is_believing/event_stream/events.rb | |
# !> 44 /Users/xjxc322/.gem/ruby/2.5.0/gems/seeing_is_believing-3.4.0/lib/seeing_is_believing/event_stream/producer.rb | |
# !> 45 /Users/xjxc322/.rubies/ruby-2.5.0/lib/ruby/2.5.0/x86_64-darwin17/socket.bundle | |
# !> 46 /Users/xjxc322/.rubies/ruby-2.5.0/lib/ruby/2.5.0/x86_64-darwin17/io/wait.bundle | |
# !> 47 /Users/xjxc322/.rubies/ruby-2.5.0/lib/ruby/2.5.0/socket.rb | |
# !> 48 /Users/xjxc322/.rubies/ruby-2.5.0/lib/ruby/2.5.0/timeout.rb | |
# !> 49 /Users/xjxc322/.gem/ruby/2.5.0/gems/seeing_is_believing-3.4.0/lib/seeing_is_believing/the_matrix.rb | |
# !> 50 /Users/xjxc322/.rubies/ruby-2.5.0/lib/ruby/2.5.0/prettyprint.rb | |
# !> 51 /Users/xjxc322/.rubies/ruby-2.5.0/lib/ruby/2.5.0/pp.rb | |
# !> 52 /Users/xjxc322/.gem/ruby/2.5.0/gems/seeing_is_believing-3.4.0/lib/seeing_is_believing/customize_pp.rb | |
# !> 53 /Users/xjxc322/.rubies/ruby-2.5.0/lib/ruby/2.5.0/x86_64-darwin17/fiddle.bundle | |
# !> 54 /Users/xjxc322/.rubies/ruby-2.5.0/lib/ruby/2.5.0/fiddle/function.rb | |
# !> 55 /Users/xjxc322/.rubies/ruby-2.5.0/lib/ruby/2.5.0/fiddle/closure.rb | |
# !> 56 /Users/xjxc322/.rubies/ruby-2.5.0/lib/ruby/2.5.0/fiddle.rb | |
# !> | |
# !> [NOTE] | |
# !> You may have encountered a bug in the Ruby interpreter or extension libraries. | |
# !> Bug reports are welcome. | |
# !> For details: http://www.ruby-lang.org/bugreport.html | |
# !> | |
# !> [IMPORTANT] | |
# !> Don't forget to include the Crash Report log file under | |
# !> DiagnosticReports directory in bug reports. | |
# !> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment