On Wed, Feb 05, 2003 at 06:00:43AM +0900, Mauricio FernáÏdez wrote: > But now, what happens if I do: > > ... > def no_redef(*args) > @no_override ||= [] > args.each { |i| @no_override << i } > @no_override.freeze > end > ... > > Is it impossible enough now? ;-) Not quite. Here are my 5 solutions: # Solution 1: Redefine Array#+ class B < Unbreakable::A def a; puts "You won!"; end Array.class_eval do def +(x) return [] end end def a; puts "You won!"; end end # Solution 2: Redefine Array#index class B < Unbreakable::A def a; puts "You won!"; end Array.class_eval do def index(id) return nil end end def a; puts "You won!"; end end # Solution 3: Redefine Fixnum#== class B < Unbreakable::A def a; puts "You won!"; end Fixnum.instance_eval do define_method(:==) { |x| true } end def a; puts "You won!"; end end # Solution 4: Use alias_method to create an alias for alias_method so # that I can still create aliases in the derived class. class B < Unbreakable::A def a; puts "You won!"; end Module.instance_eval do alias_method :alias_method_2, :alias_method end def b; puts "You won!"; end alias_method_2 :a, :b end # Solution 5: Use set_trace_func to capture all bindings; use this so # that any method that any calls __no_redef_list__ are equivalent to # "return". class B < Unbreakable::A def a; puts "You won!"; end call_stack = [] current_call = nil set_trace_func(proc {|*args| if args[3] == :__no_redef_list__ then eval "return", call_stack[4] end case args[0] when 'call' call_stack.unshift(current_call) when 'return' call_stack.shift() end current_call = args }) def a; puts "You won!"; end set_trace_func nil end > My ultimate goal with this contest is seeing if it is at all possible to > prevent redefinition unconditionally, against all attacks. My suspicion is that this is not possible without modifying the interpreter. I also suspect that protecting against all "attacks" is unnecessary, and that protecting the programmer against shooting himself in the foot is sufficient. Paul