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