TL;DR

Unicode の文字を 8 ビットのバイトの列で表す文字エンコーディング。1 文字を 1〜4 バイトで表し、ASCII と互換性がある。RFC 3629 で定められている。

なぜ必要か

RFC 3629 によると、U+0000 から U+007F までの文字は US-ASCII と同じ 1 バイトの値になるので、ASCII だけの文字列はそのまま正しい UTF-8 の文字列でもある。また、ASCII のバイト値はマルチバイトの列の中に現れないので、ASCII のバイトを解析するソフトウェアでも UTF-8 を安全に扱える。

仕組み

扱う範囲は U+0000 から U+10FFFF までで、UTF-16 のサロゲートに使う U+D800 から U+DFFF は除かれる。コードポイントの範囲によって、使うバイト数と先頭のビットの形が決まる。

コードポイントの範囲バイト数ビットの形
U+0000〜U+007F10xxxxxxx
U+0080〜U+07FF2110xxxxx 10xxxxxx
U+0800〜U+FFFF31110xxxx 10xxxxxx 10xxxxxx
U+10000〜U+10FFFF411110xxx 10xxxxxx 10xxxxxx 10xxxxxx

各範囲は重ならないので、1 つの文字の正しい表し方は 1 つに決まる。C0、C1、F5〜FF のバイト値は、正しい UTF-8 には現れない。

注意点

RFC 3629 は、デコーダが不正な列をデコードしないよう求めている。必要以上に長い表し方(たとえば C0 80 を U+0000 と読む)を受け入れると、検査をすり抜けられてしまう。RFC は、2001 年に /../ を長い表し方で書き換えた攻撃が Web サーバに広く行われたことを例に挙げている。

関連

出典