La risposta breve è: probabilmente si desidera evitare utilizzando class_eval
come questo.
Ecco una spiegazione del codice:
Il %{hello}
è solo un altro modo di scrivere una stringa letterale in Ruby, senza doversi preoccupare di fuggire virgolette doppie o singole all'interno della stringa:
%{hello "world"} == "hello \"world\"" # => true
Lo val
nel codice è un argomento del metodo in fase di definizione.
Il class_eval
viene utilizzato per definire alcuni metodi calcolando il testo che si scriverà per eseguire la definizione e quindi valutarla. Non è necessario qui, a proposito. Un codice equivalente sarebbe:
class Module
def attr_ (*syms)
syms.each do |sym|
define_method "#{sym}=" do |val|
instance_variable_set "@#{sym}", val
end
end
end
end
Questo è solo equivalente al builtin attr_writer
.
Aggiornamento: Non ci può effettivamente essere una differenza significativa tra i due ...
La versione class_eval
è vulnerabile se non ci si può fidare l'argomento syms
. Per esempio:
class Foo
attr_ "x; end; puts 'I can execute anything here!'; val=42; begin; val"
end
La versione class_eval
stamperà "Posso eseguire nulla qui" due volte, dimostrando che può eseguire qualsiasi cosa. La versione define_method
non stampa nulla.
Questo type of code è stato fondamentale per creare major vulnerability per tutte le app Rails installate.
fonte
2010-06-09 06:24:34
Ho copiato il pastebin direttamente (e corretto la scrittura). Presumo che l'ultimo '}' sia mal riposto; dovrebbe essere dopo 'val', non dopo' end' –
Non dovresti lasciare uno spazio tra un identificatore di metodo e i parenti che seguono. Ruby ti avviserà quando lo farai. –