Executing code in a variable

Z

Zangief Ief

Hello,

I have a Ruby code stocked into a Ruby variable like this:

buffer = ' puts "Hello World!" '

Is there a way for execute the current code by using buffer variable ?

Thanks
 
S

Sebastian Hungerecker

Zangief said:
I have a Ruby code stocked into a Ruby variable like this:

buffer = ' puts "Hello World!" '

Is there a way for execute the current code by using buffer variable ?

eval buffer


HTH,
Sebastian
 
D

David A. Black

Hi --

Sure, you can use eval, eg.

irb(main):002:0> eval 'puts "Hello world"'
Hello world
=> nil

However, eval should be usually avoided. Instead Ruby has the methods
instance_eval, class_eval and module_eval, which works the same as
eval but the argumented is executed in the scope of the current object/
class/module.

The main advantage of instance/class/module_eval over eval, though, is
that they can take a block and therefore you don't have to evaluate a
string. If you do this:

obj.instance_eval(str)

it's no better or worse, from the point of view of safety, than using
eval.


David

--
Rails training from David A. Black and Ruby Power and Light:
INTRO TO RAILS June 9-12 Berlin
ADVANCING WITH RAILS June 16-19 Berlin
INTRO TO RAILS June 24-27 London (Skills Matter)
See http://www.rubypal.com for details and updates!
 
R

Robert Klemme

Hi --



The main advantage of instance/class/module_eval over eval, though, is
that they can take a block and therefore you don't have to evaluate a
string. If you do this:

obj.instance_eval(str)

it's no better or worse, from the point of view of safety, than using
eval.

It is slightly better because with #instance_eval you can control what
"self" is set to and avoid a certain class of issues:

irb(main):001:0> class Foo
irb(main):002:1> attr_accessor :bar
irb(main):003:1> def work1(s)
irb(main):004:2> eval s
irb(main):005:2> end
irb(main):006:1> def work2(s)
irb(main):007:2> Object.new.instance_eval(s)
irb(main):008:2> end
irb(main):009:1> end
=> nil
irb(main):010:0> f=Foo.new
=> #<Foo:0x7ff7acf4>
irb(main):011:0> f.bar="important"
=> "important"
irb(main):012:0> f.work2 "@bar='messed'"
=> "messed"
irb(main):013:0> f.bar
=> "important"
irb(main):014:0> f.work1 "@bar='messed'"
=> "messed"
irb(main):015:0> f.bar
=> "messed"
irb(main):016:0>

But this is just a gradual difference - there is still enough damage
that can be done by evaluating strings or arbitrary code.

irb(main):016:0> f.work2 "puts 'ooops!';exit 1"
ooops!

robert@fussel ~

Kind regards

robert
 
D

David A. Black

Hi --

It is slightly better because with #instance_eval you can control what "self"
is set to and avoid a certain class of issues:

irb(main):001:0> class Foo
irb(main):002:1> attr_accessor :bar
irb(main):003:1> def work1(s)
irb(main):004:2> eval s
irb(main):005:2> end
irb(main):006:1> def work2(s)
irb(main):007:2> Object.new.instance_eval(s)
irb(main):008:2> end
irb(main):009:1> end
=> nil
irb(main):010:0> f=Foo.new
=> #<Foo:0x7ff7acf4>
irb(main):011:0> f.bar="important"
=> "important"
irb(main):012:0> f.work2 "@bar='messed'"
=> "messed"
irb(main):013:0> f.bar
=> "important"
irb(main):014:0> f.work1 "@bar='messed'"
=> "messed"
irb(main):015:0> f.bar
=> "messed"
irb(main):016:0>

But this is just a gradual difference - there is still enough damage that can
be done by evaluating strings or arbitrary code.

irb(main):016:0> f.work2 "puts 'ooops!';exit 1"
ooops!

That's the thing -- I think it's more a string thing, and the dangers
of untrusted input (which can really do anything), than the question
of what self is, since the untrusted input problem can always reassert
itself.


David

--
Rails training from David A. Black and Ruby Power and Light:
INTRO TO RAILS June 9-12 Berlin
ADVANCING WITH RAILS June 16-19 Berlin
INTRO TO RAILS June 24-27 London (Skills Matter)
See http://www.rubypal.com for details and updates!
 
R

Robert Dober

As David I am not sure that instance_eval is safer than eval. As the
following example shows a save eval can be done by deleting all
dangerous methods before evalling:

module Kernel
class << self
methods.each do |m|
next if /^__/ === m
Object::send :remove_method, m
end
end
instance_methods.each do |m|
next if /^__/ === m
Object::send :remove_method, m
remove_method m
end
end


eval %<system "ls -l">

Now this might not often be very useful though as we do not have a
sandbox or to put it better, it is much work to get out
of the sandbox again as we have to redefine all methods again (well I
did not safe them in the first place here). Furthermore my sandbox is
empty!!!

Is there an easy way to do this?

Cheers
Robert
 
C

Christopher Dicely

As David I am not sure that instance_eval is safer than eval. As the
following example shows a save eval can be done by deleting all
dangerous methods before evalling:

module Kernel
class << self
methods.each do |m|
next if /^__/ === m
Object::send :remove_method, m
end
end
instance_methods.each do |m|
next if /^__/ === m
Object::send :remove_method, m
remove_method m
end
end


eval %<system "ls -l">

Now this might not often be very useful though as we do not have a
sandbox or to put it better, it is much work to get out
of the sandbox again as we have to redefine all methods again (well I
did not safe them in the first place here). Furthermore my sandbox is
empty!!!

Is there an easy way to do this?

Well, we could use _why's Freaky Freaky Sandbox:
http://code.whytheluckystiff.net/sandbox/
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top