[contest] Code challenge

This challenge is quite uncommon since it isn’t ‘algorithmic’ nor ‘obfuscating’.
You might want to play with this if you enjoy messing around with
singletons.

[NOTE: read the end of the message!]

···

Your mission, should you choose to accept it, is to fill in the code
below so that its execution terminates without error and the output
is
You won!

module NoOverloading
def no_redef(*args)
@no_override ||=
args.each { |i| @no_override << i }
end

def no_redef_list
supmethods =
(ancestors - [self]).each do |i|
begin
supmethods += ( i.no_redef_list || )
rescue NameError
end
end
(@no_override || ) + supmethods
end

def inherited sub
class << sub
def method_added(id)
return if no_redef_list.index(id) == nil
remove_method id
end
def alias_method a, b
# catcha!
end
self.freeze
end
end
self.freeze
end

module Unbreakable
class A
extend NoOverloading
no_redef :a
def a; puts “You lost!”; end
end

class Caller
def self.foo(arg)
raise “Only classes derived from A!” unless arg.kind_of?
Unbreakable::A
arg.a
end
end
Caller.freeze
A.freeze
self.freeze
end

class B < Unbreakable::A
def a; puts “You won!”; end

PUT YOUR CODE HERE!

end

Unbreakable::Caller.foo( B.new )

Details

You are expected to subclass Unbreakable::A and find a way to override
method #a. Normally all your code should be in the indicated position.
Class B must be directly derived from Unbreakable::A. The following is
not a valid solution:
class B
def a; puts “You won!”; end
def kind_of? a
true
end
end

Warning

This mission is, to the best of my current knowledge, impossible.
_________________________________________________________________


_ _

__ __ | | ___ _ __ ___ __ _ _ __
'_ \ / | __/ __| '_ _ \ / ` | ’ \
) | (| | |
__ \ | | | | | (| | | | |
.__/ _,
|_|/| || ||_,|| |_|
Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com

…Deep Hack Mode – that mysterious and frightening state of
consciousness where Mortal Users fear to tread.
– Matt Welsh

2 things:

···

On Wed, Feb 05, 2003 at 04:48:16AM +0900, Mauricio Fernández wrote:

This challenge is quite uncommon since it isn’t ‘algorithmic’ nor ‘obfuscating’.
You might want to play with this if you enjoy messing around with
singletons.

[NOTE: read the end of the message!]


_ _

__ __ | | ___ _ __ ___ __ _ _ __
'_ \ / | __/ __| '_ _ \ / ` | ’ \
) | (| | |
__ \ | | | | | (| | | | |
.__/ _,
|_|/| || ||_,|| |_|
Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com

To kick or not to kick…
– Somewhere on IRC, inspired by Shakespeare

Hi,

You are expected to subclass Unbreakable::A and find a way to override
method #a. Normally all your code should be in the indicated position.
Class B must be directly derived from Unbreakable::A. The following is
not a valid solution:
class B
def a; puts “You won!”; end
def kind_of? a
true
end
end

Warning

This mission is, to the best of my current knowledge, impossible.

Is this a valid answer?

class B < Unbreakable::A
def a; puts “You won!”; end
# PUT YOUR CODE HERE!
p Unbreakable::A.instance_eval{@no_override.clear}
def a; puts “You won!”; end
end

						matz.
···

In message “[contest] Code challenge” on 03/02/05, Mauricio Fernández batsman.geo@yahoo.com writes:

I guess yes.
To be honest I thought of that but either overlooked its potential or
forgot to freeze the class iv. (can’t remember) :slight_smile: Wish I could say I
left it as a back-door, but that is not the case.

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? :wink:

My ultimate goal with this contest is seeing if it is at all possible to
prevent redefinition unconditionally, against all attacks.

And I learn a great deal along the way, too.

···

On Wed, Feb 05, 2003 at 05:01:28AM +0900, Yukihiro Matsumoto wrote:

Hi,

In message “[contest] Code challenge” > on 03/02/05, Mauricio Fernández batsman.geo@yahoo.com writes:

You are expected to subclass Unbreakable::A and find a way to override
method #a. Normally all your code should be in the indicated position.
Class B must be directly derived from Unbreakable::A. The following is
not a valid solution:
class B
def a; puts “You won!”; end
def kind_of? a
true
end
end

Warning

This mission is, to the best of my current knowledge, impossible.

Is this a valid answer?

class B < Unbreakable::A
def a; puts “You won!”; end
# PUT YOUR CODE HERE!
p Unbreakable::A.instance_eval{@no_override.clear}
def a; puts “You won!”; end
end


_ _

__ __ | | ___ _ __ ___ __ _ _ __
'_ \ / | __/ __| '_ _ \ / ` | ’ \
) | (| | |
__ \ | | | | | (| | | | |
.__/ _,
|_|/| || ||_,|| |_|
Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com

Never make any mistaeks.
– Anonymous, in a mail discussion about to a kernel bug report

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? :wink:

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

···

On Wed, Feb 05, 2003 at 06:00:43AM +0900, Mauricio Fernández 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? :wink:

Not quite. Here are my 5 solutions:

Ouch!

Solution 1: Redefine Array#+

Solution 2: Redefine Array#index

Solution 3: Redefine Fixnum#==

Solution 4: Use alias_method to create an alias for alias_method so

that I can still create aliases in the derived class.

I guess I’d have to freeze everything I use inside NoOverloading to
prevent these and modify alias_method on Module…
Another possibility is implementing my own cheap Array class.

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”.

And remove Kernel.set_trace_func.

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.

Was rather thinking of another way to do Rubyrobots without using safe
levels, that’s all.

At least I learned something in the process, and first thing: forget
about doing code contests for some time until I know quite a lot more :wink:

I’ll keep “closing holes” on the Wiki in case anybody is interested on
seeing if this will ever work.

···

On Wed, Feb 05, 2003 at 07:31:49AM +0900, Paul Brannan wrote:

On Wed, Feb 05, 2003 at 06:00:43AM +0900, Mauricio Fernández wrote:


_ _

__ __ | | ___ _ __ ___ __ _ _ __
'_ \ / | __/ __| '_ _ \ / ` | ’ \
) | (| | |
__ \ | | | | | (| | | | |
.__/ _,
|_|/| || ||_,|| |_|
Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com

Alan Cox wrote:
[…]

No I didnt. Someone else wrote that. Please keep attributions
straight.
– From linux-kernel