14
Help us understand the problem. What are the problem?

More than 5 years have passed since last update.

posted at

PHPの文字エンコーディング検出はアテにならない

一身上の都合で文字エンコーディングと戦った時のメモ

PHPにおける文字列のエンコーディングはphp-mbstringモジュールで提供されている。
mb_detect_encodingはデフォルトではASCIIとUTF-8しかチェックしてくれない。
mb_detect_orderでチェックするエンコーディング形式を指定することができる。
だがしかし、対して検出精度はよくない。
不適切なエンコーディングで変換された場合、脆弱性になり得る。

テスト環境

  • OS : CentOS7
  • PHP : 7.0.11

エンコードテスト

UTF-8の文字列をmb_convert_encodingで各文字エンコーディングで変換し、mb_detect_encodingmb_check_encodingで検出させる。

    $str = 'てすと';

    $enc = [
      'UTF-8',
      'UTF-7',
      'ASCII',
      'EUC-JP',
      'SJIS',
      'eucJP-win',
      'SJIS-win',
      'JIS',
      'ISO-2022-JP',
      'Unicode',
    ];
    mb_detect_order($enc);

    foreach ($enc as $e) {
      $encoded = mb_convert_encoding($str, $e, 'UTF-8');
      var_dump(
            $e,
            $encoded,
            mb_detect_encoding($encoded),
            mb_check_encoding($encoded)
      );
    }

結果

エンコード var_dump mb_detect_encoding mb_check_encoding
UTF-8 てすと UTF-8 true
UTF-7 +MGYwWTBo- UTF-8 true
ASCII ??? UTF-8 true
EUC-JP "" EUC-JP true
eucJP-win "" EUC-JP true
SJIS "" SJIS true
SJIS-win "" SJIS true
JIS \$B\$F\$9\$H(B UTF-8 true
ISO-2022-JP \$B\$F\$9\$H(B UTF-8 true
Unicode 0f0Y0h UTF-8 true

SJISとかは一部表示されていない(バイナリとして解釈されている?)けどエンコーディングは取得できていた。
mb_check_encodingはすべての場合で検出できていた。
しかし適切に検出できているのか、とにかくtrueを返す残念な子なのか調べてみる。

エンコード検出テスト

    $str = 'てすと';

    $enc = [
      'UTF-8',
      'UTF-7',
      'ASCII',
      'EUC-JP',
      'eucJP-win',
      'SJIS',
      'SJIS-win',
      'JIS',
      'ISO-2022-JP',
      'Unicode',
    ];
    mb_detect_order($enc);

    foreach ($enc as $e) {
      $s = mb_convert_encoding($str, $e, 'UTF-8');
      $arr = [];
      foreach ($enc as $e2) {
        $arr[$e2] = mb_check_encoding($s, $e2);
      }
      var_dump($e, $arr);
    }

結果

チェック\エンコ UTF-8 UTF-7 ASCII EUC-JP eucJP-win SJIS SJIS-win JIS ISO-2022-JP Unicode
UTF-8 o o o o o o
UTF-7 o o o
ASCII o o o o o
EUC-JP o o o o o o o
eucJP-win o o o o o o o
SJIS o o o o o o o o o o
SJIS-win o o o o o o o o o o
JIS o o o o o
ISO-2022-JP o o o o o
Unicode o o o o o o o o

o…trueが返ってきたところ
縦がチェックしたエンコード、横が検出対象のエンコード。
予想以上にアテにならないようです。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
14
Help us understand the problem. What are the problem?