Using a string as executable code

I need to store one line method calls as strings in my db and then apply
them to an object. For example, I would store “name.upcase” in the db
and then somehow call person.name.upcase. Any idea how I might pull this
off?

Thanks,

Peter

Peter M. wrote:

I need to store one line method calls as strings in my db and then apply
them to an object. For example, I would store “name.upcase” in the db
and then somehow call person.name.upcase. Any idea how I might pull this
off?

Thanks,

Peter
Don’t Do It!

Peter M. wrote:

I need to store one line method calls as strings in my db and then apply
them to an object. For example, I would store “name.upcase” in the db
and then somehow call person.name.upcase. Any idea how I might pull this
off?

Well, you could do

result = “name.upcase”.split(".").inject(person) do |object, method|
object.send(method)
end

but storing code in a database smells. Perhaps it would be better to
find another approach that avoids storing the code in the first place

On Thu, 03 Apr 2008 20:42:28 -0500, Paul McMahon wrote:

end

but storing code in a database smells. Perhaps it would be better to
find another approach that avoids storing the code in the first place

Your answer also smells. I’d use instance_eval.

result = person.instance_eval “name.upcase”

–Ken

Thanks for the input guys. instance_eval is exactly what I was looking
for.

I realize storing code in a database is kind of a funny idea, but I
don’t see a better alternative for the problem I face. I need to
generate an array of object customized strings, specially selected from
a pool of about 500 string functions. The only alternative I see is
defining about 300 extra frivolous string methods in my model and
selecting among those based on database values. That doesn’t seem any
less smelly.

What, specifically, concerns your the most about storing code in a
database? The risk of it becoming stale as your app changes? Performance
issues?

Thanks Again,

Peter

Paul McMahon wrote:

Well, you could do

result = “name.upcase”.split(".").inject(person) do |object, method|
object.send(method)
end

but storing code in a database smells. Perhaps it would be better to
find another approach that avoids storing the code in the first place

Or

eval “object.#{object.stored_code}”

But really. This sounds like a horrendously bad idea.

On Apr 4, 2008, at 10:37 AM, Peter M. wrote:

realize storing code in a database is kind of a funny idea, but I
don’t see a better alternative for the problem I face. I need to
generate an array of object customized strings, specially selected
from
a pool of about 500 string functions. The only alternative I see is
defining about 300 extra frivolous string methods in my model and
selecting among those based on database values. That doesn’t seem any
less smelly.

there are many easy ways to handle this

i don’t know what you mean by ‘string function’ but:

cfp:~ > cat a.rb
module StringMethods
class << self
def a
p :a
end

 def b
   p :b
 end

 def c
   p :c
 end

end
end

class Module
def string_methods *list
list.flatten.each do |m|
module_eval <<-code
def #{ m }(*a, &b)
StringMethods.#{ m }(*a, &b)
end
code
end
end
end

class Model
string_methods %w( a b )
end

m = Model.new

m.a
m.b
m.c

cfp:~ > ruby a.rb
:a
:b
a.rb:38: undefined method `c’ for #Model:0x278f8 (NoMethodError)

a @ http://codeforpeople.com/

The problem with code in the database is … the database. If there is
a vulnerability in the way you store things in the database, a
malicious user could execute arbitrary code on your server through the
pipe you open.

a.instance_eval “uname -a” —> print system name
a.instance_eval “whoami” —> print user name
… explore, find a security weakness, create an account, go in and
steal the house !

It is good practice to keep some doors closed, just in case.

Gaspard

2008/4/4, Peter M. [email protected]:

Gaspard B. wrote:

The problem with code in the database is … the database. If there is
a vulnerability in the way you store things in the database, a
malicious user could execute arbitrary code on your server through the
pipe you open.

a.instance_eval “uname -a” —> print system name
a.instance_eval “whoami” —> print user name
… explore, find a security weakness, create an account, go in and
steal the house !

It is good practice to keep some doors closed, just in case.

Gaspard

2008/4/4, Peter M. [email protected]:

Thanks for your response Gaspard. The code entering part of my app is
only for my app’s backend and will not be publicly accessible. I
definitely need to take measures to ensure it stays that way though.

ara.t.howard wrote:

there are many easy ways to handle this

i don’t know what you mean by ‘string function’ but:

Thanks for your response. All I mean by ‘string function’ is a bit of
code that produces a string. Using my example, ‘person.name’ and
‘person.name.upcase’ are different string functions. I don’t know if I’m
using the right terminology, but that’s what I mean. If I was to define
all of these ‘string functions’ as individual methods, it would be a lot
of additional hard code and I would still have these method names locked
into the db.

On Apr 4, 2008, at 2:01 PM, Peter M. wrote:

into the db.
i think you are missing the point:

(‘a’ … ‘z’).each do |m|

define_method(m){ m }

end

defines 26 methods - did you read my code? you easily define these
compactly in one module and cherry pick them into a specific class
with zero db code involved.

why don’t you spell out your exact problem and we can show you how.

cheers.

a @ http://codeforpeople.com/

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Peter M. wrote:
|
| Thanks for your response Gaspard. The code entering part of my app is
| only for my app’s backend and will not be publicly accessible. I
| definitely need to take measures to ensure it stays that way though.

It won’t. That would beat all the odds of established computer security
track records.

Another place to consider: You are introducing one more point of failure
for you app, as well as a dependency that might not be necessary.

Did you look at metaprogramming? Marshal?

And a question you might want to ask yourself: Do I want to be starring
on DailyWTF as “the developer before me”?

  • – Phillip G.
    -----BEGIN PGP SIGNATURE-----
    Version: GnuPG v1.4.8 (MingW32)
    Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iEYEARECAAYFAkf2suUACgkQbtAgaoJTgL8kbwCfSX4wUj5WdDnxz42+YOPyGfQd
d8IAoIblsuA62L5ur9R7XxHeSOzO3erJ
=IMHY
-----END PGP SIGNATURE-----

OK. So your problem is offering database stored templates to your users.

I have solved this problem for zena by creating a custom template
language called zafu. The template is compiled to erb and saved as a
file.

To manage showing attributes of objects, this is how I worked this out
(simplified):

  1. in the model, I declare readable attributes:
    class Page
    zafu_readable :name, :created_at, :title, …
    end

  2. zafu code:
    <r:show attr=‘title’/>

  3. compile template (done once when changed, not on every call to the
    template)
    erb_code << Page.zafu_readable?(attribute) ? “<%= @node.#{attribute}
    %>” : “bad attribute ‘#{attribute}’”

If you want to ‘render’ the template on each call, you could just keep
the ‘readable?’ idea:

Example with “person.name” :

template: [[person:name]]

template.gsub (/[[(\w):(\w)]]/) do
object = $1
field = $2
if object = get_object(object)
if object.class.readable_attribute?(field)
object.instance_eval field
else
“invalid attribute ‘#{field}’ for object of class
‘#{object.class}’”
end
else
“invalid object ‘#{object}’”
end
end

This is much more secure, avoids the fields table and keeps Model
information in the model. If you are in rails, you could also use the
‘attr_protected/attr_accessible’ notion.

Gaspard

2008/4/5, Peter M. [email protected]:

Phillip G. wrote:

And a question you might want to ask yourself: Do I want to be starring
on DailyWTF as “the developer before me”?

Haha, point taken. I’m not familiar with metaprogramming or marshall.
I’m looking into both.

ara.t.howard wrote:
did you read my code?

I did, but I must not understand all of it. Sorry.

ara.t.howard wrote:

why don’t you spell out your exact problem and we can show you how.

My db schema has a ‘templates’ table, a ‘fields’ table as well as a
‘template_fields’ join table that connects ‘fields’ to ‘templates’.

‘fields’ needs to contain information to produce a customized text
string for a particular object. Intuitively, I thought I needed to store
string generating code as a string in ‘fields’ and execute it against my
object. It was suggested I could do that like this:

person.instance_eval field.code

I use the resulting string and the field’s ‘name’ to assemble a hash for
each field connected to a template:

  rehash = {}
  for field in template.fields
    rehash[field.name] = person.instance_eval field.code
  end

I then use the hash of generated strings and field names for a find and
replace function.