Hatena::ブログ(Diary)

Islands in the byte stream

2010-08-22

テンプレートエンジンの自動エスケープ機能について

最近Xslateの自動エスケープ機能について考えていたのですが、これは「この機能によって安全性が高まる」というものではなく(結果的にそうでないものより安全ではありますが)、むしろテンプレートエンジンとしてはこれこそ正しい振る舞いなのではないかと思うに至りました。

この「値を渡すと、ソースコードに埋め込む際に適当に加工する」という振る舞いは、SQLプレースホルダの振る舞いがまさにそうです。SQLに値を埋め込む際、アプリケーションでいちいち値をエスケープするというのは危険であり、避けるべきです。可能であれば常にプレースホルダを使うという方針をとるだけで、エスケープ問題について余計なことを考える必要はなくなります。

テンプレートエンジンについても同じこと。テンプレートに値を埋め込む時は、そのまま渡せばいいのです。これを手動で行わせるのは、プレースホルダに埋め込む値のエスケープの有無をユーザーに行わせるようなもの。そんなRDBMSがあったとしたら使いものにならないでしょう。HTML用のテンプレートエンジンで自動エスケープ機能がないということは、プレースホルダに埋め込む値を手動でエスケープしなければならないRDBMSのように使いにくいものなのではないでしょうか。

テンプレートエンジンが特殊なのは、別のHTMLソースコードを埋め込む必要性がしばしばあるという点ですが、これも「そのまま埋めこむ」よう指示するRAWマーカーによって自然な形で解決しました。いまや、この振る舞いこそ正しいといえます。

この考えに基づいて、Xslate 0.2000からはescapeオプションを廃止します。その変わり、typeオプションを導入し、生成するもののcontent typeに合わせて「html」「xml」「text」のいずれかを指定できるようにします。「text」は旧来の「escape => "none"」に相当しますが、これはメールなどのテキストを生成するためのものであり、HTML/XMLの生成で「text」を指定するべきではありません。

perlcodesampleperlcodesample 2010/08/23 01:09  一般的な観点で考えると、「テンプレートの生成」と「HTMLのエスケープ」は独立しているのではないでしょうか?(たまたまHTMLの生成にテンプレートエンジンが使われることが多いというだけで)
 SQLのエスケープはRDBMSの特殊文字のエスケープであって、RDBMSと密結合しています。「テンプレートエンジン」と「HTMLエスケープ」は疎結合ではないでしょうか。

gfxgfx 2010/08/23 11:32 HTMLもplain textも生成する汎用テンプレートエンジンをうたうなら、その通りだと思います。しかし、HTML用のテンプレートエンジンならば、HTMLの特殊文字のエスケープをするくらい密結合していてもいいと思います。
そういうわけで、テンプレートエンジンを生成するタイミングでcontent typeを指定できるようにしたのです。もちろん「汎用」を前面に打ち出すなら、HTMLをデフォルトにするのではなく、content typeの指定を必須にするべきだとは思います。まあ、実際にはHTMLの生成が一番多いだろうということで、デフォルトはHTMLになってますが。
ならばなぜText::名前空間か、ということになりますが、これはTemplate::ToolkitがTemplate::という名前空間を占有しているため、やむを得ず選択しているだけなのでしょうがないですね。

perlcodesampleperlcodesample 2010/08/23 22:03  Text::XslateはHTML用のテンプレートエンジンということですね。Webフレームワークに組み込まれることが想定されないなら、利用者から見ればその動きのほうが安全ですね。安全性第一という視点を重視しているのですね。

gfxgfx 2010/08/24 10:11 そうなりますね。テキスト用テンプレートエンジンにも転用はできますが、デフォルトではHTML用です。

perlcodesampleperlcodesample 2010/08/24 12:43  Xslateがこんなに早くなる理由はなんですかね。テンプレートを解析した後のテンプレートの構築って、解析後の状態で含まれている文字列と、パラメータの値を順番に連結していくだけだと思っていたので、こんなに差がでるのは、びっくりしました。

gfxgfx 2010/08/24 13:05 詳しくはYAPC::Asiaで解説するつもりですが、いろいろな点で最適化してあるのが積み重なってるので一概にこれとはいえませんねー。おそらく最大の要因はVirtual Machineの実行性能そのものがPerlのそれよりも速いことですかね。そのかわり、細かなところ(たとえばデストラクタの起動のタイミング)でPerlほどきめ細かな制御ができないようになっていますけど、テンプレートエンジンだからこんなもんでいいだろう、という判断です。
他にも、文字列連結を高水準のPerl API を使わないようにして高速化してあったり、malloc()をできるだけ少なくなるようにしていたりと、pure Perlではできないようなことをいろいろやってます。
その結果、「解析後の素の文字列とパラメータの連結」そのものの速度がだいぶ違うってことですね。

perlcodesampleperlcodesample 2010/08/24 18:51 丁寧な解説、ありがとうございました。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/gfx/20100822/1282469200