1. 導入
Web開発において、XSS(クロスサイトスクリプティング)対策としての `htmlspecialchars()` の利用は必須です。しかし、実務でマルチバイト文字(日本語など)を扱う際、意図せず出力が空になったり、文字化けが発生したりする経験はありませんか。これは、PHPのデフォルトエンコーディング設定と、処理対象のデータが一致していないことが原因です。本記事では、この問題を未然に防ぐための正しい引数の指定方法を解説します。
2. 基礎知識
`htmlspecialchars()` は、特殊文字をHTMLエンティティに変換する関数です。この関数が正常に動作するためには、内部で「どのエンコーディング方式として文字列を解釈するか」を決定する必要があります。
PHP 5.4.0以降、デフォルトのエンコーディングは `UTF-8` になりました。もし、システム内部で `Shift_JIS` や `EUC-JP` など、UTF-8以外のエンコーディングを混在させている場合、関数は「不正なバイトシーケンス」として文字列を処理できず、結果として空文字を返してしまうことがあります。
3. 実装/解決策
解決策は非常にシンプルで、`htmlspecialchars()` の第3引数に、現在処理している文字列のエンコーディングを明示的に指定することです。
また、第2引数の `flags` には、シングルクォートとダブルクォートを両方変換する `ENT_QUOTES` を指定するのがセキュアな実装の定石です。
4. サンプルプログラム
以下のコードは、UTF-8で記述されたPHPファイル内で、あえてShift_JISに変換した文字列を安全に出力する例です。
5. 応用・注意点
現場で注意すべき点は、`ENT_IGNORE` フラグの使用を避けることです。
一部の古いドキュメントやネット上の情報では、エンコーディングエラーを無視するために `ENT_IGNORE` を推奨するものがありますが、これは極めて危険です。不正なバイト列を無理やり通すことで、ブラウザが誤った解釈を行い、結果としてXSSの脆弱性を誘発する可能性があります。
また、現代のPHP開発では、プロジェクト全体で `UTF-8` に統一し、`mb_internal_encoding(‘UTF-8’)` を設定した上で、`htmlspecialchars()` の引数を省略せず `htmlspecialchars($text, ENT_QUOTES, ‘UTF-8’)` と書く(あるいは、より簡潔な `htmlspecialchars($text, ENT_QUOTES)` が使える環境を整える)ことが、バグを防ぐための最も賢明なプラクティスです。