JPCERT コーディネーションセンター

STR05-C. 文字列リテラルの参照には const へのポインタを使用する

ナロー文字列リテラルの型は char 型の配列であり、ワイド文字列リテラルの型は wchar_t 型の配列である。しかし、文字列リテラルは(charwchar_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
0753

部分的に実装済み
参考資料
[Corfield 1993]  
[Lockheed Martin 2005]   AV Rule 151.1
翻訳元

これは以下のページを翻訳したものです。

STR05-C. Use pointers to const when referring to string literals (revision 92)

Top へ

Topへ
最新情報(RSSメーリングリストTwitter