class_eval injection


#1

關於class_eval 很多人都說盡量不要用,原因是因為可以直接把字串變成method 這裏有個問題,請問有可能在view 端的eval instance 被啟動嗎?感覺eval的程式碼在前端要hack起來的可能性不大,是否有範例可以知道class_eval的危險性?


#2

首先,如果不是為了 meta programming,也就是類似 Rails 的 relation ( has_many / belongs_to ),而是為了方便自己一個小部分而弄在 view 內,而不是努力的寫好一點的 helper … 你在幹啥?

class_eval 是動態執行 code,尤其動態建立 method,但如果隨機且數量太大,你根本就是害死你家的記憶體,畢竟每個動態新增的程式都會先搶記憶體空間,且不會 free 掉(等人 reuse),再來是危險性?

這篇demo有用這篇特殊字母表示
http://jokercatz.blogspot.tw/2015/05/ruby-general-delimited-input.html

class Car
  def initialize(color)
    @color = color
  end
  def color
    @color
  end
  def set_eval(str)
    Car.class_eval(str)
  end
end
blue_car = Car.new('blue')
blue_car.color #=> "blue"
blue_car.set_eval("def initialize(*argv);puts %x(ls);end")
red_car = Car.new('red')
 #=> call system "ls"

這樣的寫法我是不敢用啦X"D…尤其自己餵一個 string 進去就可以建立個很邪惡的鬼的時候,我寫一個正確的寫法給你看就是,通常這類的 meta programming 建議和 method_missing 相同,裡面當入口點,且要 call 到正確的 method 去,類似

class Tank
  def get_attribute(symbol)
    @attributes ||= {}
    return @attributes[symbol]
  end
  def set_attribute(symbol , value)
    @attributes ||= {}
    return @attributes[symbol] = value
  end
  def self.set_part(name)
    name = name.to_s
    if name.match(/^[a-z_]{3,}$/)
      self.class_eval %Q%
        def give_me_#{name}
           return get_attribute "#{name}"
        end
        def set_the_#{name}(value)
           return set_attribute "#{name}" , value
        end
      %
    end
  end
end

然後用於繼承

class SuperTank < Tank
  set_part :gun
  set_part :gas 
end
super_tank = SuperTank.new
super_tank.set_the_gun('Hellfire')
super_tank.give_me_gun #=> "Hellfire"
super_tank.set_the_gas('CookingOil')
super_tank.give_me_gas #=> "CookingOil"

anyway 重要的是觀念,進來的東西一定要過濾過,然後建立的method只做簡單的事物,基本上就是"轉手",其中的 set_part 基本上就是 Rails 那一票外掛的製法,也就這樣而已就是

and 這篇我應該回過你類似的問題才是


這邊就寫真實的行為就是