Skip to content

Instantly share code, notes, and snippets.

@albb0920
Last active September 23, 2016 20:00
Show Gist options
  • Save albb0920/e3d419dae3ce8819e0ac522fe8da12ec to your computer and use it in GitHub Desktop.
Save albb0920/e3d419dae3ce8819e0ac522fe8da12ec to your computer and use it in GitHub Desktop.
Inject method accessor for specific Hash instance PoC
# ====
# PoC: dot access to specific hash instance
# ===
x = {a: 1, b:2}
# override method_missing
original_method_missing = x.method(:method_missing)
x.define_singleton_method :method_missing do|name, *args, &block|
return x[name] if x.key? name
original_method_missing.bind(self).call(name, *args, &block)
end
puts "Can now access hash via method, x.a => #{x.a}"
begin
Marshal.dump(x)
rescue Exception => e
puts "But this breaks Marshal: #{e.class}: #{e}"
end
# solution: hook Marshal.dump()
x.instance_variable_set(:@_polluted_by_hash_magic_accessors, true)
original_marshal_dump = Marshal.method(:dump)
Marshal.define_singleton_method :dump do|*args|
obj = args[0]
if obj.instance_variable_defined? :@_polluted_by_hash_magic_accessors
obj.singleton_class.send :remove_method, :method_missing
obj.remove_instance_variable :@_polluted_by_hash_magic_accessors
end
original_marshal_dump.call(*args)
end
puts "Marshal now works: #{Marshal.load(Marshal.dump(x)).inspect}"
@albb0920
Copy link
Author

The goal of this PoC is to reduce pollution to Hash.
Still needs:

  • Re-inject dot accessor after Marshal.dump()
  • Delete singleton method recursively

Now I think this path is too hacky, maybe a wrapper object that is_a(Hash) would be a better solution.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment