STR05-C. 文字列リテラルの参照には const へのポインタを使用する
ナロー文字列リテラルの型は char
型の配列であり、ワイド文字列リテラルの型は wchar_t
型の配列である。しかし、文字列リテラルは(char
もwchar_t
も)名目上は定数であり、そのため const
修飾により保護すべきである。このレコメンデーションは 「DCL00-C. 不変(immutable)オブジェクトは const 修飾する」の特殊なケースであり、「STR30-C. 文字列リテラルを変更しない」の補足でもある。
const
修飾を追加しはじめると、結局プログラム全体にわたって const
修飾を追加するはめになるかもしれない。つまりひとつconst
修飾を追加したら、もっと必要になってしまうというように。この現象は const 中毒と呼ばれることがあり、「EXP05-C. const 修飾をキャストではずさない」の違反を引き起こすことが多い。const
修飾はすぐれた考え方ではあるが、既存のコードを修飾するコストが、得られる価値を上回るかもしれない。
違反コード (ナロー文字列リテラル)
以下のコードでは、const
キーワードが省略されている。
char *c = "Hello";
c[0] = 'C'
のような文がこのコード例の宣言のあとに置かれたとすると、コードはエラーなくコンパイルされるだろうが、文字列リテラルが定数と見なされるため、代入文の結果は未定義となる。
適合コード (変更不可能な文字列)
以下の適合コードでは、ポインタ c
が参照する文字が const
修飾されており、異なる値を代入しようとしてもエラーになる。
const char *c = "Hello";
適合コード (変更可能な文字列)
文字列が変更されることを意図している場合は、代入ではなく初期化を使用する。以下の適合コードでは、c
は変更可能な char
型配列であり、対応する文字列リテラルの内容で初期化されている。
char c[] = "Hello";
このため、c[0] = 'C'
などの文は有効であり期待通りに動作する。
違反コード (ワイド文字列リテラル)
以下のコードでは、const
キーワードが省略されている。
wchar_t *c = L"Hello";
c[0] = L'C'
のような文が上記の宣言のあとに置かれたとすると、コードは問題なくコンパイルされる可能性が高いが、文字列リテラルが定数と見なされるため、代入文の結果は未定義となる。
適合コード (変更不可能な文字列)
以下の適合コードでは、ポインタ c
が参照する文字が const
修飾されており、異なる値を代入しようとしてもエラーになる。
wchar_t const *c = L"Hello";
適合コード (変更可能な文字列)
文字列が変更されることを意図している場合は、代入ではなく初期化を使用する。以下の適合コードでは、c
は変更可能な wchar_t
型配列であり、対応する文字列リテラルの内容で初期化されている。
wchar_t c[] = L"Hello";
このため、c[0] = L'C'
などの文は有効であり期待通りに動作する。
リスク評価
文字列リテラルを変更すると、未定義の動作が引き起こされ、結果としてプログラムの異常終了やサービス運用妨害(DoS)の脆弱性が引き起こされる。
レコメンデーション |
深刻度 |
可能性 |
修正コスト |
優先度 |
レベル |
---|---|---|---|---|---|
STR05-C |
低 |
低 |
低 |
P3 |
L3 |
自動検出(最新の情報はこちら)
ツール |
バージョン |
チェッカー |
説明 |
---|---|---|---|
Compass/ROSE |
|
|
|
ECLAIR |
1.1 |
conststr |
実装済み |
LDRA tool suite |
V. 8.5.4 |
157 S |
部分的に実装済み |
PRQA QA-C | 8.1 |
0752 |
部分的に実装済み |
参考資料
[Corfield 1993] | |
[Lockheed Martin 2005] | AV Rule 151.1 |
翻訳元
これは以下のページを翻訳したものです。
STR05-C. Use pointers to const when referring to string literals (revision 92)