EN JP CN

チュートリアル 1 - C/C++ KAST チェッカーの作成

チュートリアル 1 - C/C++ KAST チェッカーの作成

チュートリアル 1 - C/C++ KAST チェッカーの作成

チュートリアル 1 - C/C++ KAST チェッカーの作成

 

このチュートリアルでは、単純な C/C++ KAST チェッカーの作成方法について説明します。

kwcreatechecker を実行する

チェッカーファイルを作成するディレクトリに移動し、次のオプションを指定して kwcreatechecker を実行します。また、Windows の場合は VS プロンプトでこれを行います。

kwcreatechecker --language cxx --type kast --code MY.C.KAST.CHECKER

--code オプションはチェッカーに割り当てる名前を指定します。

注: エラー ID (チェッカー名) では、マルチバイト文字はサポートされていません。また、255 文字までという制限があります。

ディレクトリは--code で指定した名前で作成されます。このディレクトリには、チェッカースタブファイルが含まれます。上述の例では、ディレクトリの名前は MY.C.KAST.CHECKERです。MY.C.KAST.CHECKER ディレクトリには以下が含まれます。

  • チェッカー設定ファイル (checkers.xmlhelp.xml)
  • テストケースサンプル (testcase.cc)
  • build file (ビルドファイル) (Makefile)

最も単純なテストケースを作成する

チェッカーの最初のテストケースはできるだけ単純なものにしてください。チェッカーの開発が進むとともに、より複雑なケースを追加してテストすることができます。

このチュートリアルで作成するチェッカーは、if ステートメントでの変数代入を検出します。等価演算子 a == b を代入演算子 a = b (2 つの等号ではなく単一の等号) として間違って入力しがちです。それでも結果は有効な C/C++ コードになります。次にこの Klocwork エラーを生成する最も単純なコードフラグメントを示します。

void f(int a, int b) {  
 if (a = b) { //Error: assignment of b to a in if statement  
 /* do stuff */
 }
}

testcase.cc ファイルのテンプレートコードを、このコード (MY.C.KAST.CHECKER/testcase.cc) に置き換えます。

Checker Studio を使用して目的の KAST ノードを検索する

単純なテストケースを作成したら、次のステップは Checker Studio を開くことです。

  1. デスクトップで Checker Studio アイコンをダブルクリックするか、コマンドラインで次のように入力します。
    kwstudio
    
  2. Checker Studio の [ソースコード] セクションにテストケースの抜粋を貼り付けて、KAST ノード名、コード例および階層情報を表示します。これらは、チェッカーで特定する指摘へのパスを追跡する KAST 式の構成要素になります。言語ボタンをウィンドウの右上隅に忘れずに設定してください。
  3. [ソースコード] ペインで、抜粋内の if をクリックします。

    AST で IfStmt ノードがハイライトされます。これはKAST 式内の目的の最初のノードです。

  4. ツリーノードを選択して F1 キーを押すか、[表示] > [コンテキストヘルプ] ウィンドウをクリックし、式のコンテキスト依存ヘルプを表示します。[ソースコード] ペインの下にコンテキスト依存ヘルプが表示され、スーパータイプやサブタイプ、使用できる関数などのノード情報が提供されます(画像の鮮明度の理由により、このチュートリアルの図には [コンテキストヘルプ] パネルは表示されません)。
  5. AST で IfStmt を拡張します。

    IfStmt には子 CondThen、および Else があります。このチェッカーは if ステートメントの条件式を処理します。

  6. Cond::AnyExpr ノードを拡張します。

    Image:KAST_tutorial1_1_GWYN_10.png

    Cond には 1 つの子 BinaryExpr があり、IfStmt にはバイナリ式 (BinaryExpr) の条件句 (Cond) が含まれることを示します。

  7. [ソースコード] ペインで '=' をクリックします。

    これにより BinaryExpr がハイライトされ、属性が左下の属性テーブルに表示されます。

    Image:KAST_tutorial1_2_GWYN_10.png

    注: 属性が表示されない場合は、[属性を表示] アイコンをクリックします。現在選択されているノードの属性のみが表示されます。
  8. Value (KTC_OPCODE_ASSIGN)を書き留めます。

    AST ノードが揃ったら、KAST 式のドラフトを作成できます。

KAST 式のドラフトを作成する

前のステップで特定したノードは、IfStmtCond、および BinaryExpr です。これを KAST 式にまとめると、次のようになります。

//IfStmt / Cond::BinaryExpr [ @Op = KTC_OPCODE_ASSIGN ]

KAST は、式ノードの Op 属性の値を返す組み込み関数、getOperationCode() を提供します。このチュートリアルでは、特定の属性を明示的にクエリする代わりにこの関数を使用します。これにより、次の KAST ステートメントが得られます。

//IfStmt / Cond::BinaryExpr [ getOperationCode() = KTC_OPCODE_ASSIGN ]

この KAST 式は、AST で、条件ステートメントでの割り当てを含む if ステートメントを検索します。(KAST 式の要素の詳細については、C/C++ KAST 構文リファレンスを参照してください。)

KAST 式が完成したら、次のステップはその式をテストすることです。

KAST 式をテストする

  1. 上記の KAST 式を Checker Studio の [パターン] ペインに入力します。
     
    式と一致した AST ノードが選択され、対応するソースコードフラグメントがハイライトされます。
     
    Image:KAST_tutorial_1_3_GWYN_10.png
  2. 必要に応じて KAST 式とテストケースを調整し、再テストします。Checker Studio は、ソースコードおよび AST を検索し、自動的に変更に対応します((Image:KAST_tutorial1_auto_button.png 自動パターン適用がオンであることを確認してください)。
     
    現在ハイライトされている式に適した関数のコンテキスト依存ヘルプを見ることができます。

テストケースに複雑度を加える

KAST チェッカー開発プロセスでの次のステップは、テストケースにテストを追加することです。追加できるテストは次のとおりです。

  • 誤検知テスト - チェッカーが特定の条件に対してエラーを生成しないことを確認します。
  • より複雑なテスト - チェッカーが特殊なケースまたは複雑度の高いケースに対してエラーを生成することを確認します。

このチュートリアルのサンプルチェッカーでは、次の 3 つの誤検知テストケースを追加します。

  • 非代入ブール演算
  • ブール等価演算
  • 複合式での割り当て

これらのケースでは、Klocwork エラーは生成されません。

1.testcase.cc のコードを次のように変更します。

  void f(int a, int b)
  {
   if (a = b) { /* ERROR - assignment in condition */ 
   }
   
   if (a > b) { /* OK - no assignment */
   }
 
   if (a == b) { /* OK - equal check, not assignment */  
   }
  
   if ((c = getchar()) != EOF) { /* OK - assignment as part of more complex expression */  
   }
  } 

2.Checker Studio に新しいコードを貼り付け、テストを再実行します。

Image:KAST_tutorial_1_4_GWYN_10.png

結果は、誤検知が生成されなかった (すべてのテストケースが処理された) ことを示します。

KAST 式を checkers.xml ファイルに追加する

チェッカーの KAST 式が完成しテストされたら、kwcreatechecker を実行して生成した checkers.xml ファイルにそれを追加できます。このファイルが最初に生成されると、その値にはエラー ID、重要度、メッセージ、タイトル、およびサンプル KAST 式が自動的に指定され、チェッカーを定義するために何を変更する必要があるかが明らかになります。

このような特殊な場合、この XML ファイルの pattern 要素に着目し、次のように変更します。

<pattern> 
    // IfStmt / Cond::BinaryExpr [ getOperationCode() = KTC_OPCODE_ASSIGN ]  
</pattern>   
  1. サンプル KAST 式をテスト済みの KAST 式で置換します。<error> ノードの属性も編集できます。 たとえば、タイトル属性を "Variable assignment in if statement" に、メッセージ属性を "Possible undesired variable assignment in an if statement" に変更できます。
  2. ファイルを保存します。

チェッカーのヘルプを作成する

help.xml ファイルを編集することによりチェッカードキュメントを作成できます。 これは、最初にチェッカーを作成すると、他のチェッカーファイルとバンドルされます。

少なくともチェッカーの役に立つ説明を入力します。 一方、このチェッカーが検出する典型的なミスにより攻撃にさらされる可能性のあることを説明するリスク、コードをどのように修正してこのリスクに対応するかを説明する防止など、他のセクションの内容を入力することが有益と思われることもあるかもしれません。

チェッカーが展開されると、入力したヘルプコンテンツは自動的にオンラインヘルプコレクションに統合されます。

チェッカーをビルドする

チェッカーの KAST 式を checkers.xml ファイルに追加し、ヘルプを作成したら、チェッカーをビルドできます。これを簡単にするために、kwcreatechecker は初回実行時に Makefile をチェッカーディレクトリに追加します。

Unix または OS/X (または Windows 以外のその他のオペレーティングシステム) の場合は、以下を実行します。

make install buildspec

Windows の場合は、Visual Studio コマンドプロンプトを使用していることを確認し、以下を実行します。

nmake install buildspec

これによって、以下が生成されます。

  • 展開に適したチェッカーのコードを使用できる zip ファイル
  • kwcheck または kwbuildproject を使用してコンパイル済みのチェッカーをテストするための build specification (ビルドスペック) ファイル

チェッカーをテストする

  1. 選択したディレクトリにアーカイブファイルを解凍します。
     
    ヒント:チェッカースタブファイルを作成した同じディレクトリにアーカイブファイルを解凍することもできます。
     
    C/C++ チェッカーがプラットフォーム固有の場合は、xml ファイルを <username>/.klocwork/<plugins>/<platform-name> にコピーします。
     
    サーバー プロジェクト レベルでチェッカーを展開する準備が完了したら、デスクトップからチェッカーをアンインストールします。
     
    詳細については、デスクトップへのチェッカーパッケージの展開を参照してください。
  2. 同じディレクトリに次のようにローカルプロジェクトを設定します。
     
    kwcheck create -b <build_specification>
    
     
    フィールド <build_specification> は make install buildspec または nmake install buildspecを使用して作成されました。デフォルトでは、build specification (ビルドスペック) は現在の作業ディレクトリの kwinject.out に書き込まれます。
  3. 次のように kwcheck を実行して、テストケースで指摘が検出されたかどうか確認します。
     
    kwcheck run
    
     
    チェッカーはテストケースから指摘を検出します。
  4. 結果に満足した段階で、チェッカーをサーバーに展開できます。