Project

General

Profile

Bug #12927 » segfault.rb

Script that reproduce the issue - eritiro (Emiliano Ritiro), 11/12/2016 09:54 PM

 
GC.disable

# This class holds a reference to the duplicated sym proc
module Warden
class SessionSerializer
end
end

# This class duplicates the sym proc when defines a method
# the duplicated sym proc references the ep of the original sym proc
module Warden
class Manager
class << self
def serialize_into_session(scope = nil, &block)
puts 'lets define the method'
method_name = scope.nil? ? :serialize : "#{scope}_serialize"
Warden::SessionSerializer.send :define_method, method_name, &block
end
end
end
end

# our config file creates the original sym proc
# the original proc is a cfunc_proc_t which self-contains its block.env as part of the struct
Warden::Manager.serialize_into_session(&:to_h)

# at this point we have 2 different &:to_h procs
# both has the same block.ep pointer
# which points to the cfunc_proc_t struct of the original &:to_h
# proc_memsize(original_ptr) => 64
# proc_memsize(duplicated_ptr) => 40 (because it uses the ep of the original)


# we wont get rid of the original sym proc until the sym_proc_cache loses the reference
# to the original sym_proc
# To destroy the cache for &to_h I just need another sym proc with the same module
# (id % SYM_PROC_CACHE_SIZE) to have a cache collision
# since I don't want to calculate that magic number, let's convert to proc all our symbols!
p "let's fill the sym proc cache!"
Symbol.all_symbols.each(&:to_proc)

# this will start the GC. destroying our original reference.
p 'destroy the original reference to the &to_h proc'
GC.start
GC.enable

# now we only keep the duplicated sym_proc which references a ep which is not in use.
p 'fill the heap with garbage'
require 'rails'
# with little luck, the block->ep[1] will have a number that is not 0 nor a valid VALUE
# KABOOM!!

(1-1/2)