STR00-C. 文字の表現には適切な型を使用する
文字列は、ソフトウェアエンジニアリングにおける基本概念であるが、C 言語には文字列は標準データ型としては存在しない。C 言語では、null 終端バイト文字列(NTBS: Null-Terminated Byte Strings)は、最初の null 文字で終端される、null 文字を含む連続した文字の並びで成り立ち、文字列リテラルを表すための形式として利用されている。C 言語では、シングルバイト文字列、マルチバイト文字列、およびワイド文字列が利用できる。シングルバイト文字列とマルチバイト文字列は、どちらも null 終端バイト文字列として表現され、「ナロー文字列」と呼ばれることもある。
null 終端バイト文字列へのポインタは、文字列の 1 文字目を参照する。文字列の長さは null 文字に先行するバイト数とし、文字列の値は、それに含まれる文字の値が順番に並んだ値の列とする。
ワイド文字列は、最初の null ワイド文字で終端され、かつそれを含む連続したワイド文字(wchar_t
型)の並びである。ワイド文字列を指すポインタは、そのワイド文字列の先頭の(最も低いアドレスをもつ)ワイド文字を指すポインタとする。ワイド文字列の長さは、null ワイド文字に先行するワイド文字の個数とし、ワイド文字列の値は、それに含まれるワイド文字のコード値が順番どおりに並んだ値の列とする。
null 終端バイト文字列は、文字の配列として実装されているため、配列と同じ問題を起こしやすい。このため、配列のルールおよびレコメンデーションが null 終端バイト文字列にも適用される。
C 標準は以下の考え方に基づいて文字型を使い分けている。もっとも、この考え方は 1 箇所にまとめて書かれているわけではない。
signed char
と unsigned char
- 小さな整数値に適している。
「単なる」char
- 文字列リテラルの要素の型。
- 文字集合の一部の文字データを、整数型データではなく(正負の違いが特に意味を持たない)文字型データとして扱う場合に使われる。
int
EOF
(負の値)または、unsigned char
として解釈されint
に変換される文字データ。fgetc()
、getc()
、getchar()
、およびungetc()
の返り値の型。また、fgetc()
の返り値を<ctype.h>
などの文字列処理関数への引数に使うこともある。- 文字定数の型。その値は単なる
char
の値がint
に変換されたものである。
文字を int
として使う方法が 2 通りあることにより、混乱が生じる可能性がある(ひとつは unsigned char
+ EOF
として、もうひとつは int
に変換される単なる char
として)。たとえば、isspace('\200')
は char
が符号付きの場合に未定義の動作となる。
unsigned char
- 文字列比較関数の内部で使われる。これらの関数は、文字データに対する処理を行うが、文字列比較の結果は単なる
char
が符号付きかどうかに関係なく行われる。 - 操作対象が任意の型である可能性があり、
fwrite()
の場合のようにその操作対象のすべてのビットにアクセスする必要がある場合に使われる。
他の整数型の場合と異なり、unsigned char
には次のような独自の特性がある。
unsigned char
型の [...] オブジェクトに格納される値は純 2 進表記法で表現される(C 標準 [ISO/IEC 9899:2011] セクション 6.2.6.1)。
ここで、純 2 進表記法は次のように定義される。
バイナリの桁 0 および 1 を使用する整数の位置表現で、連続するビットで表現される値は加算方式をとり、1 から始まり、最上位ビット以外は連続する 2 の整数乗で乗算される。1 バイトは
CHAR_BIT
ビットから構成され、unsigned char
型の値の範囲は 0 から 2CHAR_BIT
− 1。(セクション 6.2.6、fn. 49)
つまり、unsigned char
型のオブジェクトはパディングビットを持たないことがあるため、トラップ表現がない場合もある。そのため、任意の型の非ビットフィールドオブジェクトを(memcpy()
などにより) unsigned char
の配列にコピーし、表現を 1 バイトずつ検査することができる。
wchar_t
- ワイド文字は自然言語の文字データに対して使われる。
リスク評価
文字と文字列の表現方法を理解することにより、ソフトウェアの脆弱性につながるありがちなプログラミングエラーの多くを排除できる。
レコメンデーション |
深刻度 |
可能性 |
修正コスト |
優先度 |
レベル |
---|---|---|---|---|---|
STR00-C |
中 |
中 |
低 |
P12 |
L1 |
関連するガイドライン
CERT C++ Secure Coding Standard | STR00-CPP. Represent characters using an appropriate type |
ISO/IEC TR 24731-1:2007 |
参考資料
[ISO/IEC 9899:2011] | Section 6.2.6, "Representations of Types" |
[Seacord 2013] | Chapter 2, "Strings" |
翻訳元
これは以下のページを翻訳したものです。
STR00-C. Represent characters using an appropriate type (revision 31)