• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:evalを使うinputがある場合も安全に運用する)

evalを使うinputがある場合も安全に運用するための方法

このQ&Aのポイント
  • evalを使うinputがある場合も安全に運用するための方法として、エスケープを行います。
  • 四則演算子、数字、括弧以外は削除され、式として成立しない文字列は計算できません。
  • エスケープの表記位置はevalを実行する前であればどこでも良いです。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.22

>!"#$%&',:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ >をInputに入れてアラートの処理が実行されるか確かめてみます 「catch内が実行されるか(アラートの処理が実行されるか)」ではなく >r = r.replace(/([^0-9\.\-\/\*\+\(\) ]+)/g, ' '); >r = r.replace(/([\*\/])[ \+\-\*\/]*([\+\-])[ ]*([0-9\.\(]+)/g, '$1$2$3'); >r = r.replace(/[\+\-][ \+\-\*\/]*([\+\-])[ ]*([0-9\.\(]+)/g, '$1$2'); >r = r.replace(/(^|\()[ \+\-\*\/]*([\+\-])/g, '$1$2'); >r = r.replace(/(^|\()[ \+\-\*\/]*[\*\/]/g, '$1'); >r = r.replace(/([\+\-\*\/])[ \+\-\*\/]*[\*\/][ ]*([0-9\.\(]+)/g, '$1$2'); >r = r.replace(/([ ]+)/g, ' '); ↑この「r」変数の値が''(ヌル文字)(文字が何も無い文字列)になるか、実際の「r」変数の値を表示してみて下さい。

その他の回答 (21)

回答No.11

>replaceというのは第一引数の文字列を第二引数の文字列に変換する関数のようですね。 正確に言うと正規表現で変換します。 >>r = r.replace(/([\*\/])[ \+\-\*\/]*([\+\-])[ ]*([0-9\.\(]+)/g, '$1$2$3'); >であれば*や+,-などを123に変更しているのですかね? 違います。 不正な「四則演算子」を除去してます。 例えば「*/+-123.456」は「*-123.456」に変換されます。 >r = r.replace(/(^|\()[ \+\-\*\/]*([\+\-])/g, '$1$2'); ↑こちらは、例えば「(*/+-」は「(-」に変換されます。 正規表現は下記ページを参照して下さい。 正規表現 - JavaScript | MDN https://developer.mozilla.org/ja/docs/Web/JavaScript/Guide/Regular_Expressions

okweb12345
質問者

お礼

正規表現がわかっていないと理解するのが難しそうですが、 とりあえず危険な記載を安全な記載に変換しているのですね。 ただこの記述をどこに記載したらいいのですか?evalを使う直前に記載したらいいのですか?

回答No.10

>回答No.9 amanojaku1 >>r = r.replace(/([\*\/])[ \+\-\*\/]*([\+\-])[ ]*([0-9\.\(]+)/g, '$1$2$3'); >>r = r.replace(/[\+\-][ \+\-\*\/]*([\+\-])[ ]*([0-9\.\(]+)/g, '$1$2'); >>r = r.replace(/(^|\()[ \+\-\*\/]*([\+\-])/g, '$1$2'); >>r = r.replace(/(^|\()[ \+\-\*\/]*[\*\/]/g, '$1'); >>r = r.replace(/([\+\-\*\/])[ \+\-\*\/]*[\*\/][ ]*([0-9\.\(]+)/g, '$1$2'); >↑これで(四則演にならない)不正な「四則演算子」を除去してます。 >ここはバグの入り込む余地がありますが、それほど複雑でもないので問題ないと思われます。 ↑これで(四則演算にならない)不正な「四則演算子」を除去してます。 ここはバグの入り込む余地がありますが、それほど複雑でもないので これで問題ないと思われます。

okweb12345
質問者

お礼

いつもお手伝いいただき大変ありがとうございます。 自分でも調べてみたところ replaceというのは第一引数の文字列を第二引数の文字列に変換する関数のようですね。 >>> >>r = r.replace(/([\*\/])[ \+\-\*\/]*([\+\-])[ ]*([0-9\.\(]+)/g, '$1$2$3'); であれば*や+,-などを123に変更しているのですかね? >>> var str = 文字列 str.replace(対象の文字, 置換する文字); 「文字列」の中から「対象の文字」を検索し、一致した文字を「置換する文字」に変換してくれるのが「replace()」の基本的な機能になります。

回答No.9

>回答No.5 amanojaku1 >r = r.replace(/([^0-9\.\-\/\*\+\(\) ]+)/g, ' '); ↑これで「四則演算子、数字、括弧」以外を除去してます。 これで基本的に関数類は実行できません。 ここは簡単なのでバグの入り込む余地はありません。 >r = r.replace(/([\*\/])[ \+\-\*\/]*([\+\-])[ ]*([0-9\.\(]+)/g, '$1$2$3'); >r = r.replace(/[\+\-][ \+\-\*\/]*([\+\-])[ ]*([0-9\.\(]+)/g, '$1$2'); >r = r.replace(/(^|\()[ \+\-\*\/]*([\+\-])/g, '$1$2'); >r = r.replace(/(^|\()[ \+\-\*\/]*[\*\/]/g, '$1'); >r = r.replace(/([\+\-\*\/])[ \+\-\*\/]*[\*\/][ ]*([0-9\.\(]+)/g, '$1$2'); ↑これで(四則演にならない)不正な「四則演算子」を除去してます。 ここはバグの入り込む余地がありますが、それほど複雑でもないので問題ないと思われます。 もしバグがあっても不正な「四則演算子」が残るだけなので、基本的に関数類は実行できません。

回答No.8

#7 小数対応してなかったorz でも単純な書き足し付け足しでいけそうだし ほとんど答えがすでに別レスにあるし、 主さんに自分で頑張っていただきますか

回答No.7

<input type="text" name="gakunen" value="" onKeyPress="Calculator(this.value, event.keyCode)"> <script type="text/javascript"> <!-- function Calculator(a, kcode){ var r,match; try{ if (!(13==kcode)){return;} r=a.replace(/\s/,''); if(/[^0-9\+\-\*\/\(\)]/g.test(r)){throw '半角数字と()+-*/で入力してください';} if(match=r.match(/(\([\+\*\/]|[\+\-\*\/]\)|\(\)|\)\(|[^\+\-\*\/\(]\()/)){ throw '不正な入力:'+match[0]; } r.replace(/[\+\-\*\/]{2,}/g,function(match){ if(match.length>2 || match.substr(-1)!=='-')throw '不正な入力:'+match; return match; }); var n=0; r.replace(/[\(\)]/g,function(match){ if(match=='('){n++;} else if(match==')'){n--;} if(n<0){throw '閉じられていない括弧があります';} return match; }); if(n!=0){throw '閉じられていない括弧があります';} alert(r+' = '+eval(a)); }catch(e){ if(typeof(e)=='string'){alert(e);} else{alert(e.message);} } } // --> </script> 処理止めてメッセージ返すほうが どこで引っかかったかわかるから好き 検索巡回にわざわざreplace使うのはどうかとも思ったけど それ以外に一致部分をcallbackで都度さらに 判定する手段が思い当たらなかったし 多分どっか引っかかったところで即処理を中断できる方が 効率いいと思ったのでとりあえずreplaceで ここまで判定したらelse{alert(e.message);}に行くことないかな?

回答No.6

以前JavaScriptでマクロのような記述を見た事があったのですが、もしかしてjQueryなどをインクルードしていたのかもしれません(jQueryでevalが影響を受けるのかは分かりませんが)。 まあ、どちらにしろ「四則演算子、数字、括弧」以外は除去されるので、エスケープとかの必要はないでしょう(バグがなければの話ですが)。

回答No.5

>エスケープしたいのですが エスケープの意味はコーテションで囲むみたいな意味なのか?わかりませんが、 >r = r.replace(/([^0-9\.\-\/\*\+\(\) ]+)/g, ' '); >r = r.replace(/([\*\/])[ \+\-\*\/]*([\+\-])[ ]*([0-9\.\(]+)/g, '$1$2$3'); >r = r.replace(/[\+\-][ \+\-\*\/]*([\+\-])[ ]*([0-9\.\(]+)/g, '$1$2'); >r = r.replace(/([\+\-\*\/])[ \+\-\*\/]*[\*\/][ ]*([0-9\.\(]+)/g, '$1$2'); >r = r.replace(/(^|\()[ \+\-\*\/]*([\+\-])/g, '$1$2'); >r = r.replace(/(^|\()[ \+\-\*\/]*[\*\/]/g, '$1'); >r = r.replace(/([ ]+)/g, ' '); ↑これは「四則演算子、数字、括弧」以外は除去されるので、エスケープとかの必要はないでしょう(まあバグがなければの話ですが)。 >バグがありましたので、修正しました (2)。 バグではありませんが、チョット修正しました。 「四則演算子、数字、括弧」以外は除去されます。<br> また式として成立しない文字列は計算できません。<br> <input type="text" name="gakunen" value="" onKeyPress="Calculator(this.value, event.keyCode)"> <script type="text/javascript"> <!-- function Calculator(a, kcode){ var r; if (!(13==kcode)){return;} // ↑「13:Enterキー」でない場合は「return」 r = a; r = r.replace(/([^0-9\.\-\/\*\+\(\) ]+)/g, ' '); r = r.replace(/([\*\/])[ \+\-\*\/]*([\+\-])[ ]*([0-9\.\(]+)/g, '$1$2$3'); r = r.replace(/[\+\-][ \+\-\*\/]*([\+\-])[ ]*([0-9\.\(]+)/g, '$1$2'); r = r.replace(/(^|\()[ \+\-\*\/]*([\+\-])/g, '$1$2'); r = r.replace(/(^|\()[ \+\-\*\/]*[\*\/]/g, '$1'); r = r.replace(/([\+\-\*\/])[ \+\-\*\/]*[\*\/][ ]*([0-9\.\(]+)/g, '$1$2'); r = r.replace(/([ ]+)/g, ' '); try{ alert(r+' = '+eval(r)); }catch(ex){ alert(ex.message+' : '+r); } } // --> </script>

回答No.4

バグがありましたので、修正しました (2)。 「四則演算子、数字、括弧」以外は削除されます。<br> また式として成立しない文字列は計算できません。<br> <input type="text" name="gakunen" value="" onKeyPress="Calculator(this.value, event.keyCode)"> <script type="text/javascript"> <!-- function Calculator(a, kcode){ var r; if (!(13==kcode)){return;} // ↑「13:Enterキー」でない場合は「return」 r = a; r = r.replace(/([^0-9\.\-\/\*\+\(\) ]+)/g, ' '); r = r.replace(/([\*\/])[ \+\-\*\/]*([\+\-])[ ]*([0-9\.\(]+)/g, '$1$2$3'); r = r.replace(/[\+\-][ \+\-\*\/]*([\+\-])[ ]*([0-9\.\(]+)/g, '$1$2'); r = r.replace(/([\+\-\*\/])[ \+\-\*\/]*[\*\/][ ]*([0-9\.\(]+)/g, '$1$2'); r = r.replace(/(^|\()[ \+\-\*\/]*([\+\-])/g, '$1$2'); r = r.replace(/(^|\()[ \+\-\*\/]*[\*\/]/g, '$1'); r = r.replace(/([ ]+)/g, ' '); try{ alert(r+' = '+eval(r)); }catch(ex){ alert(ex.message+' : '+r); } } // --> </script>

回答No.3

>>とりあえず1*-1ができない >それは考えてませんでした、下記で対応できます。 バグがありましたので、修正しました。 「四則演算子、数字、括弧」以外は削除されます。<br> また式として成立しない文字列は計算できません。<br> <input type="text" name="gakunen" value="" onKeyPress="Calculator(this.value, event.keyCode)"> <script type="text/javascript"> <!-- function Calculator(a, kcode){ var r; if (!(13==kcode)){return;} // ↑「13:Enterキー」でない場合は「return」 r = a; r = r.replace(/([^0-9\.\-\/\*\+\(\) ]+)/g, ' '); r = r.replace(/([\+\-\*\/])[ \+\-\*\/]*([\+\-])[ ]*([0-9\.\(]+)/g, '$1$2$3'); r = r.replace(/([\+\-\*\/])[ \+\-\*\/]*[\*\/][ ]*([0-9\.\(]+)/g, '$1$2'); r = r.replace(/^[ \+\-\*\/]*([\+\-])/g, '$1'); r = r.replace(/(\()[ \+\-\*\/]*([\+\-])/g, '$1$2'); r = r.replace(/([ ]+)/g, ' '); try{ alert(r+' = '+eval(r)); }catch(ex){ alert(ex.message+' : '+r); } } // --> </script>

okweb12345
質問者

お礼

その後どうでしょうか?お忙しいところ恐縮ですがよろしくお願いします。 また、教えていただいたエスケープはなかなか難しくどこに記載したらよいかなどわからないのですが、 htmlcharacterでphpはhtmlタグを安全な文字列に簡単に変換できるようですがjavascriptにはそのような便利な関数はないのでしょうか?

回答No.2

>とりあえず1*-1ができない それは考えてませんでした、下記で対応できます。 「四則演算子、数字、括弧」以外は削除されます。<br> また式として成立しない文字列は計算できません。<br> <input type="text" name="gakunen" value="" onKeyPress="Calculator(this.value, event.keyCode)"> <script type="text/javascript"> <!-- function Calculator(a, kcode){ var r; if (!(13==kcode)){return;} // ↑「13:Enterキー」でない場合は「return」 r = a; r = r.replace(/([^0-9\.\-\/\*\+\(\) ]+)/g, ' '); r = r.replace(/([\+\-\*\/])[ \+\-\*\/]*([\+\-])[ ]*([0-9\.\(]+)/g, '$1$2$3'); r = r.replace(/([\+\-\*\/])[ \+\-\*\/]*[\*\/][ ]*([0-9\.\(]+)/g, '$1$2'); r = r.replace(/^[ \+\-\*\/]*([\+\-])/g, '$1'); r = r.replace(/([ ]+)/g, ' '); try{ alert(r+' = '+eval(r)); }catch(ex){ alert(ex.message+' : '+r); } } // --> </script>

okweb12345
質問者

お礼

>>> >r = r.replace(/([^0-9\.\-\/\*\+\(\) ]+)/g, ' '); >r = r.replace(/([\*\/])[ \+\-\*\/]*([\+\-])[ ]*([0-9\.\(]+)/g, '$1$2$3'); >r = r.replace(/[\+\-][ \+\-\*\/]*([\+\-])[ ]*([0-9\.\(]+)/g, '$1$2'); >r = r.replace(/([\+\-\*\/])[ \+\-\*\/]*[\*\/][ ]*([0-9\.\(]+)/g, '$1$2'); >r = r.replace(/(^|\()[ \+\-\*\/]*([\+\-])/g, '$1$2'); >r = r.replace(/(^|\()[ \+\-\*\/]*[\*\/]/g, '$1'); >r = r.replace(/([ ]+)/g, ' '); 文字列.replace( 検索文字列 , 置換文字列 ) 文字列の置換を行います という事なので変数rの中に入っている文字列?テキストエリアのテキスト? を上記の文字に変換するという事でしょうか? 恐らくトンチンカンですいません。 >>> if (!(13==kcode)){return;} これは上記の許可する13文字に該当しなかったら何かを返すのですか?? 初心者なのでさっぱりわかりません。

okweb12345
質問者

補足

下記のお礼コメントの件教えていただければ幸いです。 ここがわからないと前に進めないので、お忙しいところ恐縮ですがよろしくお願いします。 今処理はeval の前においておけばいいのでしょうか?

関連するQ&A