LoginSignup
6
8

More than 5 years have passed since last update.

htmlspecialcharsとFILTER_SANITIZE_SPECIAL_CHARS

Last updated at Posted at 2018-05-07

経緯

ぼく「POSTされた値を受け取るときのフィルタってなにがええんやろな~」
ぼく「お、FILTER_SANITIZE_SPECIAL_CHARS安全そうでええやん!」
~数日後~
ぼく「POSTで来た値をHTMLに出力するときにはhtmlspecialchars!常識だよね!」
~半年後~
お客様「'って入力したら'に文字化けするんだけど!!」
ぼく「ふええええ」

原因

FILTER_SANITIZE_SPECIAL_CHARS
'"<>& および ASCII 値が 32 未満の文字を HTML エスケープします。オプションで、 特殊文字を取り除いたりエンコードしたりします。

ENT_QUOTES
シングルクオートとダブルクオートを共に変換します。

つまり、

$input = filter_input(INPUT_POST,"hoge",FILTER_SANITIZE_SPECIAL_CHARS);
echo htmlspecialchars($input,ENT_QUOTES,'UTF-8');

とすると、
'"<>&が多重エスケープされてしまいます。

本来なら、入力の受け取り時はバリデーションのみ、出力時にエスケープとするのが妥当(らしい)なのですが、
PHPの除去フィルタのうちの一部が除去するだけでなくエスケープまで行っているので、こうなってしまいました。

おまけ

ヌル文字とかを弾きたかったら、FILTER_SANITIZE_STRINGFILTER_FLAG_STRIP_LOWを使って以下のようにするのをおススメします。(フィルタ名にはサニタイズが入っているが、エンコードじゃなくて除去をしてくれる。)

$input = filter_input(INPUT_POST,"hoge",FILTER_SANITIZE_STRING,FILTER_FLAG_STRIP_LOW);

注意点としては、\nなどの制御文字も弾かれてしまいます。(ASCIIで32未満なので。)
ちなみにFILTER_FLAG_STRIP_HIGHを使うとマルチバイト文字が弾かれてしまいます。英数字のみ入力のときに使えます。

どうしてもサニタイズしてほしくない人は、FILTER_UNSAFE_RAWと各種フラグを使えば良さそうです。

PHPマニュアルをよく読んで、自分に合った君だけの除去フィルタを手に入れよう!

6
8
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
8