diff --git a/data/smarty_extends/modifier.script_escape.php b/data/smarty_extends/modifier.script_escape.php index 0e04180830..064c14bc9e 100644 --- a/data/smarty_extends/modifier.script_escape.php +++ b/data/smarty_extends/modifier.script_escape.php @@ -7,38 +7,45 @@ */ function smarty_modifier_script_escape($value) { - if (is_array($value)) return $value; + // パフォーマンス低下を軽減するため文字列以外は処理しない。 + // TODO: Stringable なオブジェクトも対象とするのが安全かもしれない。しかし、この modifier は、default_modifiers に設定しているため、影響が見通せない (文字列として返して良いのか不確か)。 + if (!is_string($value)) return $value; - $pattern = "|<\/script>|javascript:|||||||"; + static $pattern; + if (is_null($pattern)) { + $pattern = "|<\/script>|javascript:|||||||"; - // 追加でサニタイズするイベント一覧 - $escapeEvents = array( - 'onmouse', - 'onclick', - 'onblur', - 'onfocus', - 'onresize', - 'onscroll', - 'ondblclick', - 'onchange', - 'onselect', - 'onsubmit', - 'onkey', - ); + // 追加でサニタイズするイベント一覧 + $escapeEvents = array( + 'onmouse', + 'onclick', + 'onblur', + 'onfocus', + 'onresize', + 'onscroll', + 'ondblclick', + 'onchange', + 'onselect', + 'onsubmit', + 'onkey', + ); - // イベント毎の正規表現を生成 - $generateHtmlTagPatterns = array_map(function($str) { - return "<(\w+)([^>]*\s)?\/?".$str."[^>]*>"; - }, $escapeEvents); - $pattern .= implode("|", $generateHtmlTagPatterns)."|"; - $pattern .= "(\"|').*(onerror|onload|".implode("|", $escapeEvents).").*=.*(\"|').*"; - - // 正規表現をまとめる - $attributesPattern = "/${pattern}/i"; - - // 置き換える文字列 - $convert = '#script tag escaped#'; + // イベント毎の正規表現を生成 + $generateHtmlTagPatterns = array_map(function($str) { + return "<(\w+)([^>]*\s)?\/?".$str."[^>]*>"; + }, $escapeEvents); + $pattern .= implode("|", $generateHtmlTagPatterns)."|"; + $pattern .= "(\"|').*(onerror|onload|".implode("|", $escapeEvents).").*=.*(\"|').*"; + $pattern = "/{$pattern}/i"; + } // マッチしたら文字列を置き換える - return preg_replace($attributesPattern, $convert, $value); + // - preg_replace は、(たとえ置換が発生しなくても) preg_match より重い。置換が発生する頻度は極めて低いはずなので、preg_match で事前判定する。 + if (preg_match($pattern, $value)) { + // 置き換える文字列 + $convert = '#script escaped#'; + $value = preg_replace($pattern, $convert, $value); + } + + return $value; } diff --git a/tests/class/modifier/Modifier_ScriptEscapeTest.php b/tests/class/modifier/Modifier_ScriptEscapeTest.php index 8c92118781..dd1f859626 100644 --- a/tests/class/modifier/Modifier_ScriptEscapeTest.php +++ b/tests/class/modifier/Modifier_ScriptEscapeTest.php @@ -62,7 +62,7 @@ public function scriptNoEscapeProvider() public function testメールテンプレート_エスケープされる($value) { $ret = smarty_modifier_script_escape($value); - $pattern = "/#script tag escaped#/"; + $pattern = "/#script escaped#/"; $this->assertRegExp($pattern, $ret); } @@ -72,7 +72,7 @@ public function testメールテンプレート_エスケープされる($value) public function testメールテンプレート_エスケープされない($value) { $ret = smarty_modifier_script_escape($value); - $pattern = "/#script tag escaped#/"; + $pattern = "/#script escaped#/"; $this->assertNotRegExp($pattern, $ret); } }