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

PRE07-C. "??" の繰り返しは避ける

"?" 2つは3文字表記の始まりを表す。C 言語規格のセクション 5.2.1.1 には次のように記載されている[ISO/IEC 9899:2011]。

次に示す文字の並び[3文字表記(trigraph sequenceという。)]がソースファイルの中にある場合、その三つの文字の並びを対応する一文字に置き換える。

??=

#

 

??)

]

 

??!

|

??(

[

 

??'

^

 

??>

}

??/

\

 

??<

{

 

??-

~

 

違反コード

このコード例では、a++ が実行されない。なぜなら、3文字表記 ??/\ に置き換えられ、a++ がコメント行と同一行に配置されてしまうからである。

// a の値はなんだろう??/
a++;
適合コード

以下のコード例は、"?" の間に空白文字をひとつ入れることにより、予期せず3文字表記にならないようにしている。

// a の値はなんだろう? ?/
a++;
違反コード

このコード例は3文字表記 ??! を含む。これは | に置き換えられる。

size_t i = /* 初期値 */;
if (i > 9000) {
   if (puts("Over 9000!??!") == EOF) {
     /* エラー処理 */
   }
}

C言語規格に適合したコンパイラを使うと、このコードの出力は Over 9000!| になる。

適合コード

以下の適合コードでは、文字列連結を用いて二つの "?" を連結している。このようにしなければ 3 文字表記の始まりと解釈されてしまう。

size_t i = /* 初期値 */;
/* i への代入 */
if (i > 9000) {
   if (puts("Over 9000!?""?!") == EOF) {
     /* エラー処理 */
   }
}

このコードは意図したとおり Over 9000!??! を出力する。

リスク評価

うっかり3文字表記をしてしまうと予期せぬ動作を引き起こすおそれがある。コンパイラによっては、3文字表記がある場合に警告を出すオプションや3文字表記を無効にするオプションを提供している。警告を出すオプションを使用し、コンパイル時に警告が出ないようなコードにせよ。(「MSC00-C. 高い警告レベルでのコンパイルで警告が出ないようにする」を参照。)

レコメンデーション

深刻度

可能性

修正コスト

優先度

レベル

PRE07-C

P2

L3

自動検出
ツール バージョン チェッカー 説明

ECLAIR

1.1

dtrigraf

実装済み
GCC V. 4.3.5  

-Wtrigraphs フラグを使用することでこのレコメンデーションの違反を検出できる

LDRA tool suite

V. 8.5.4

81 S

実装済み
PRQA QA-C 8.1 3601 部分的に実装済み
関連するガイドライン
CERT C++ Secure Coding Standard PRE07-CPP. Avoid using repeated question marks
MISRA-C Rule 4.2
参考資料
[ISO/IEC 9899:2011] Section 5.2.1.1, "Trigraph Sequences"
翻訳元

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

PRE07-C. Avoid using repeated question marks (revision 80)

Top へ

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