Pixel Pedals of Tomakomai

北海道苫小牧市出身の初老の日常

MTのセキュリティパッチ

一つ前のエントリでお世話になった時に目に入った、nlog(n)さんパッチとしてのプラグインとその可能性トラックバック



このパッチはプラグインディレクトリ plugins にインストールするものだが,普通のプラグインとは動作が異なっている。「再構築が不要」というだけでも違うことが分かる。




自分もこのパッチを当てた時、同じようなことを思った。中を見ると、問題となっているメソッドの型グロブを書き換え、処理を無理矢理変えている。



例えば、以下のような2つのファイルからなるスクリプトがあったとする。



#Bug.pm ==========
package Bug;
sub new{ bless \"$_[1]", $_[0] }
sub hello{ print "bugbugbug!\n" }
1;

#main.pl ==========
use Bug;
my $plugin_dir = "plugin";

opendir(DIR, $plugin_dir);
while(my $file = readdir(DIR)){
next if($file !~ /\.pl$/);
eval "require \"$plugin_dir/$file\";";
warn $@ if($@);
}
closedir(DIR);
my $bug = new Bug("Mike");
$bug->hello();

実行結果
bugbugbug!






見ての通り、Bug.pmのhello()メソッドにはバグがある。また、main.plはpluginと言うディレクトリにあるスクリプトを全てrequireするように出来ている。



この状態で、以下のパッチを作ると、動作が改善される。



#plugin/patch.pl ==========
*Bug::hello = sub {print "I am ${$_[0]}.\n"};

実行結果
I am Mike.





なお、書き換え前の関数のリファレンス\&Bug::helloを保存しておけば、新しい&Bug::helloの中から古いルーチンを呼ぶことも出来る。



とても便利で、perlならではと言ったところかな。応用すれば、CPANのモジュールの動きが気に食わない時にも役に立ちそう。ただし、この方法を使えばどんなサブルーチンの動作も書き換えられてしまうので、悪用すると大変危険であり、注意が必要だ。