EN JP CN

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

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

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

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

このチュートリアルでは、カスタム C# KAST チェッカーの作成方法について説明します。

kwcreatechecker を実行する

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

kwcreatechecker --language cs --type kast --code MY.CS.KAST.CHECKER

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

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

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

  • チェッカー設定ファイル (checkers.xmlhelp.xml)
  • テストケースサンプル (testcase.cs)
  • build file (ビルドファイル) (Nmakefile)
  • build specification (ビルドスペック) ファイル (buildspec.out)

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

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

class Example
{  
    public static void foo(int a, int b)
   { 
    if (a = b) //Error: assignment of b to a in if statement
      {
         /* do stuff */
      }
   }
}

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

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 には子 conditionifBody、およびelseBody があります。このチェッカーは if ステートメントの条件式を処理します。

  6. condition::Expr ノードを拡張します。

    Image:KAST_tutorial1_CS.png

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

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

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

    Image:KAST_tutorial1_CS2.png

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

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

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

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

// IfStmt / condition::BinaryExpr [ @operation = CSCONST_ASSIGN ]

この KAST 式は、AST で、条件ステートメントでの割り当てを含む if ステートメントを検索します。

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

KAST 式をテストする

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

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

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

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

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

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

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

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

class Example
{
  public static void foo(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 ((a = Console.Read()) != 0x0a) /* OK - assignment as part of more complex expression */
      {
      }
  }
}

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

Image:KAST_tutorial1_CS4.png

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

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

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

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

<pattern> 
    // IfStmt / condition::BinaryExpr [ @operation = CSCONST_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 をチェッカーディレクトリに追加します。

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

nmake install

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

  • 展開に適したチェッカーのコードを使用できる zip ファイル

チェッカーをテストする

  1. 選択したディレクトリにアーカイブファイルを解凍します。
    ヒント:チェッカースタブファイルを作成した同じディレクトリにアーカイブファイルを解凍することもできます。
    xml ファイルを<username>/.klocwork/<plugins>/csharpにコピーします。
    サーバー プロジェクト レベルでチェッカーを展開する準備が完了したら、デスクトップからチェッカーをアンインストールします。
    詳細については、デスクトップへのチェッカーパッケージの展開を参照してください。
  2. 同じディレクトリに次のようにローカルプロジェクトを設定します。
    kwcheck create -b buildspec.out
    
  3. 次のように kwcheck を実行して、テストケースで指摘が検出されたかどうか確認します。
    kwcheck run
    
    チェッカーはテストケースから指摘を検出します。
  4. 結果に満足した段階で、チェッカーをサーバーに展開できます。