JavaScriptを使っていて、文字列をプログラムとして実行する場合に便利に使えるeval関数の返り値が少し理解しづらかったので調査しました。
ちなみに、eval関数は、脆弱性の元として使用を危険視されていて、ユーザーが任意に発火できないように構築を行う必要があります。
公開サーバーで使用する場合は十分に注意して脆弱性の調査などを行うことをオススメします。
1. 数値計算
var res = eval("1+1");
> res => 2
文字列の数式は計算結果を取得できます。
2. 文字列
var res = eval("document.title");
> res = %titme%
環境変数や通常変数なども取得できます。
3. 返り値チェック
普通にreturn
var txt = "return 'aaa';";
var res = eval(txt);
> Uncaught SyntaxError: Illegal return statement(…)
evalの中からreturnをしてみると値が返るかどうかチェック
syntaxErrorという事は、関数でもないのにreturnをした為でしょう。
関数を使ってreturn
var txt = "return 'aaa';";
var res = eval((function(){txt})());
> undefined
それでは、evalの中で無名関数(即時関数)を使ってreturnしてみると。
undefinedです。
文字列にした関数でreturn
var txt = "return 'aaa';";
var res = eval("(function(){"+txt+"})()");
> "aaa"
無名関数をまるごと文字列にすることで、return値を受け取ることができました。
引数に文字列関数を挿入したパターン
var txt = "(function(){return 'aaa'})()";
var res = eval(txt);
> "aaa"
いっその事、変数の文字列を無名関数にしてみても結果は同じです。
functionチェック
functionをeval内で実行
var fn = function(){return "aaa"};
var res = eval(fn);
> undefined
正直、このevalを実行する意味はないですが、とりあえずこのままではNGなようです。
functionをeval内で実行の修正版
var fn = function(){return "aaa"};
var res = eval("'"+fn+"'");
> "aaa"
まとめ
とりあえず分かったことは、evalの中身は全て文字列(または数値)にする必要があり、大きなプログラムもfunctionで包むと書くことは可能そうだ。
これにより、外部テキストファイルに書かれているJS関数を、ajaxで読み込み、evalで実行することができるので、カスタマイズCMSっぽく利用することができるだろう。
返り値と脆弱性に気をつければ、やはりevelは武器になると思うんだが、使用頻度はあまり高くないので、使う場合はしっかりチェックしよう。
0 件のコメント:
コメントを投稿