読者です 読者をやめる 読者になる 読者になる
無料で使えるシステムトレードフレームワーク「Jiji」 をリリースしました!

・OANDA Trade APIを利用した、オープンソースのシステムトレードフレームワークです。
・自分だけの取引アルゴリズムで、誰でも、いますぐ、かんたんに、自動取引を開始できます。

セーフレベル4でのインスタンス変数の変更ではまる

セーフレベル4でも、汚染されたオブジェクトが対象であれば、インスタンス変数の変更が可能です。ただし、更新するインスタンス変数がクラス内で1度も使われていない場合、SecurityErrorとなるのでご注意。

# 指定のSAFEレベルでブロックを実行する。
def safe( level ) 
  Thread.fork {
    $SAFE = level
    yield if block_given?
  }.value
end

# テスト用クラス
class Foo
  def not_called
      @hoge
  end
end
foo = Foo.new
foo.taint #汚染

# 汚染たオブジェクトのインスタンス変数は、セーフレベル4でも変更できる。
safe( 4 ) {
  foo.instance_variable_set("@hoge", "var")
}
# ただし、インスタンス変数がクラス定義内で1度も使用されていない場合、
# 「Insecure: can't modify instance variable (SecurityError)」となる。
safe( 4 ) {
  foo.instance_variable_set("@var", "var")
}

実行結果です。@hogeは問題なく変更できますが、未知のインスタンス変数@varを変更するところで、「Insecure: can't modify instance variable (SecurityError)」が発生します。

xxx/instance_variable_set.rb:25:in `instance_variable_set': Insecure: can't intern tainted string (SecurityError)
	from xxx/instance_variable_set.rb:3:in `value'
	from xxx/instance_variable_set.rb:3:in `safe'
	from xxx/instance_variable_set.rb:24

内部的にインスタンスとかクラスの拡張みたいな扱いになっているのかな?なんとなく納得できる挙動である気はしますが。「セーフレベル4ではオブジェクトのインスタンス変数は変更できない」のかと思ってさんざん迷走してしまった・・・。orz.