UTF-8 での注意点

非最小形式の不正なエンコーディングに注意

UTF-8 は文字によって1文字あたりのバイト数が1バイトから4バイト(もしくは6バイト)と可変長なエンコーディングです。Unicode の各文字がどのようなバイト列で表現されるかは、下表のようになっています。

Unicode 文字範囲UTF-8 でのバイト列(2進数)
U+0000〜U+007F 0xxxxxxx
U+0080〜U+07FF 110xxxxx 10xxxxxx
U+0800〜U+FFFF 1110xxxx 10xxxxxx 10xxxxxx
U+10000〜U+10FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
この表から明らかなように、ASCII の文字範囲(U+0000〜U+007F)までは、本来なら1バイトで表現され、ASCII と互換のはずです。
ところが、意図的に必要以上のバイト数で文字を表現することにより、文字列のチェックをすり抜けられる可能性があります。例えば、スラッシュ / (U+002F) は、本来ならば UTF-8 での表現は 0x2F となりますが、無理矢理 2バイトで表現した場合、0xC0 0xAF となりますし、3バイトで表現した場合には 0xE0 0x80 0xAF となります。
このように、必要以上に長いバイト数を使って UTF-8 を構成することにより、単純なバイト列の比較をすり抜けられる可能性があります。この問題は、"Unicode Web Traversal" や "Path Traversal" などと呼ばれ、実際に CodeRed などでも攻撃に利用されました。
また、同じように、ヌル文字 \0 (U+0000) は、UTF-8 での正しい表現は1バイトの 0x00 ですが、2バイトで 0xC0 0x80 と表現したり、3バイトで 0xE0 0x80 0x80 と表現することができます。もし、これらを UTF-8 として受け入れてしまった場合、バイト列が 0x00 で終端していないため、使用しているライブラリなどにおいてバッファオーバーフローを引き起こす可能性が高まります。

UTF-8においては、最小形式以外の冗長なバイト列は、文字列として受け入れてはいけません。

ISO/IEC 10646 の文字範囲では、最大6バイト

Unicode での文字範囲は U+0000〜U+10FFFF に納まり、そのため UTF-8 では最大4バイトとなりますが、Unicode とは兄弟のような規格である ISO/IEC 10646 においては、文字の範囲は U+7FFFFFFF までとなり、そのため UTF-8 の最大長は6バイトになることがあります。
もしU+10FFFF を超える文字を許容するのであれば、必要なバッファのサイズは、最大文字数×4バイトよりも多くなることもありますので、バッファオーバーフローを引き起こさないように注意が必要です。