JQ Blog

コードを記述するコード

eval()

eval()を使うとコード文字列を使って処理できる。例えば、

1
2
3
array = [10, 20]
element = 30
eval("array << element") # => [10, 20, 30]

evalの問題点

evalが評価するコード文字列内でもローカル変数にアクセスできる。 そういう意味ではブロックと似ている。

1
2
v1 = 1
eval("v1") # => 1

evalとブロックどちらを使うのが良いのか。
答えは「ブロック」らしい。コード文字列(evalを用いた処理記述)は問題点がある。

コードインジェクション

外部からコード文字列を読み込んだ際に、悪意のあるコードを読み込んでしまい、
プライベート情報漏洩やハードディスクの情報を消されたりしてしまう。

1
2
3
4
5
6
7
8
9
def my_method(method)
  eval("'a'.#{method}")
end

# 悪意のあるコード プライベートな情報が表示されてしまう。
my_method(object_id; Dir.glob("*")

'a'.object_id
Dir.glob("*")

オブジェクトの汚染とセーフレベル

Rubyは安全でないオブジェクトに汚染マークを付ける。
webフォーム、コマンドライン、システム変数の読み込み文字列などを含んでいた場合、安全でないと判断する。

1
2
3
4
5
6
user_input = "User input: #{gets()}"
# 汚染されているかどうかをチェック
puts user_input.tainted?

x = 1
true

汚染マークを検知して、例外を発生させるセーフレベルという仕組みがある。
潜在的に危険な操作に対して制限をかけられる。

1
2
3
4
5
6
7
# セーフレベルを1に設定
user_input = "User input: #{gets()}"
eval user_input

x = 1
# セーフレベル1以上の場合、汚染した文字列を評価できない
SecurityError: Insecure operatiion - eval

フックメソッド

さまざまなイベントを契機に処理を行うことができる。(継承、拡張など)

1
2
3
4
5
6
7
8
9
10
11
12
13
module MyModule
  # includedがフックメソッド 
  def self.included(othermod)
    # MyModuleが拡張されると下記が処理される
    puts "MyModuleは #{othermod}にmixinされた"
  end
end

class C
  include MyModule
end

# => MymoduleはCにmixinされた

その他のフックメソッド

  • Class#inherited()
  • Module#extend_object()
  • Module#method_added()
  • Module#method_removed()
  • Module#method_undefined()

などをオーバーライドすれば、そのイベントに関連したメソッドを実行できる。

参考

http://tamata78.hatenablog.com/entry/2015/09/19/172049