フロー解析の深さの設定

フロー解析エンジンは、解析されたコードからパスを分析し、さまざまな問題を検出します。アプリケーション全体にわたって「実行される可能性があるパス」をすべて解析するのは現実的ではない場合もあるため、解析レベルの深さを設定できます。解析レベルが深いほど、発見される違反の数が増えます。ただし、パフォーマンスが低下し、若干メモリの消費量が増加します。

解析の深さは、DTP でテスト コンフィギュレーション インターフェイスを使用して設定します。  Report Center > [テスト コンフィギュレーション] > [静的解析] > [フロー解析詳細設定] > [パフォーマンス] > [解析の深さ] にアクセスし、以下のいずれかのオプションを選択します。

  • 最も浅く (最も高速): ソース コード中の最も明らかな問題だけを発見します。発見する対象は、問題が発生しているコード箇所に「問題の起点」が近い場合だけに制限されます。発見される違反の実行パスは通常、1 つの関数のいくつかの行にわたります。4 以上の関数呼び出しにわたることはまずありません。
  • 浅く (高速): [最も浅く] オプションと同様、ソース コード中の最も明らかな問題だけを発見します。ただし、[浅く] オプションは [最も浅く] オプションよりも多くの問題を検出し、より長いパスを検証できます。
  • 標準: 何十もの要素を含む実行パスにおける、多くの複雑な問題を発見します。[標準] オプションは、[浅く] オプションよりも深い解析を実行するのに加えて、より複雑な問題を探します。たとえば、「不正なフローのために1 つの関数で発生する問題」や、「解析対象プロジェクト中の異なる箇所にある異なる関数間で不適切なやり取りがあるために発生する問題」などです。多くの場合、[標準] オプションが発見する違反は、解析対象ソース コード中の重要なバグを明らかにし、そのコード行は何十行にも及びます。
  • 深く (低速): [標準] オプションで定義されているのと同等の複雑さと性質の問題を、より多く検出できます。ただし、解析速度は [標準] オプションよりも遅くなります。
  • 徹底的 (より低速): より複雑な問題を発見します。コードベースを徹底的に解析するため、時間を必要とします。しかし、アプリケーション中の異なる場所にある何百行というコードに違反パスがわたるような、非常に複雑な問題を数多く発見します。このオプションは夜間のテスト実行で使用することを推奨します。

デフォルトの解析レベルの深さは [標準] です。

タイムアウトの方針の設定

解析レベルの深さの他に、フロー解析エンジンはタイムアウト設定を利用して、妥当な時間内で解析が終了するようにします。タイムアウトの設定を行うには、DTP でテスト コンフィギュレーション インターフェイスを使用します。Report Center > [テスト コンフィギュレーション] > [静的解析] > [フロー解析詳細設定] > [パフォーマンス] > [タイムアウトの方針] にアクセスし、以下のいずれかのオプションを選択します。

  • 時間: 指定時間が過ぎると、指定したホットスポットの解析が停止します。 注意:このオプションを選択すると、レポートされる違反件数がやや不安定になる場合があります。
  • インストラクション: フロー解析エンジンのインストラクションの実行回数が指定の回数を超えると、指定したホットスポットの解析が停止します。注意: 環境に合った適切なインストラクション数を決定するには、生成されたレポートの [セットアップの問題] セクションでタイムアウト情報を確認してください。
  • オフ: タイムアウトしません。注意: このオプションを選択すると、解析が終了するまで時間がかかる場合があります。

デフォルトのタイムアウト オプションは [時間] であり、タイムアウト秒数は 60 秒です。解析中に発生したフロー解析タイムアウトについての情報を得るには、解析後に生成されるレポートで [セットアップの問題] セクションを確認してください。

解析データのスワップを有効にしたフロー解析の実行

スワップ モードでは、解析データをハードディスクに書き込みます。解析データのスワップは、インクリメンタル解析と同じ永続性記憶装置を使用し、インクリメンタル解析と似たプロセスで実行されます。大きなプロジェクトで解析を実行する場合、解析するソース コードの意味論的モデルを表す解析データが、フロー解析が使用できるすべてのメモリを消費する可能性があります。この現象が発生した場合、フロー解析は現在必要ない解析データをメモリから削除し、後でディスクから再び読み込みます。

一般的に、 Xmx JVM オプションを使って JVM ヒープのサイズを大きくしてJtestを実行することを推奨します。これはスワップを最小限にするためであり、結果としてパフォーマンスが向上します。充分なメモリがある場合、解析データのスワップは無効化しても構いません。スワップを無効化すると、コード解析の速度が上がる場合があります。

スワップ モードを有効化/無効化するには、DTP のテスト コンフィギュレーション画面を使用します。

ディスクへの解析データのスワップを有効化: デフォルトで有効です。大量のメモリを必要としない小さなサイズのプロジェクトに対してフロー解析を実行する場合、または 64-bit システムのように十分なメモリがある場合、このオプションを無効化すると、解析のパフォーマンスが向上する場合があります。

フロー解析の冗長性の設定

DTP のテスト コンフィギュレーション画面では、次のオプションを設定できます。

  • 原因が特定できない場合は違反をレポートしない: 原因を表示できない場合に違反をレポートするかどうかを指定します。
    一部のフロー解析ルールでは、フロー解析はあるポイントに至るすべての可能なパスをチェックし、すべてのパスについて特定の条件が満たされることを検証する必要があります。そのような場合、1 つの違反が複数のパスに関連付けられます (単純なケースでは、1 つの違反が 1 つのパスによって表されます)。そのような違反のすべてのパスは、違反のすべてのパスに共通する違反ポイントで終わります。ただし、別のパスがコード中の別のポイントで開始する可能性もあります。各パスの開始点が違反の原因 (コード中のポイント。それよりも後の違反ポイントのコードで特定の条件の違反を規定する) です。「複数パスの違反」でパスによって原因が異なる場合、フロー解析は違反のポイントだけを表示します (違反の原因は表示しません)。
    違反の原因から違反ポイントまでの完全なパスが表示される通常のケースと比較すると、違反ポイントだけの違反は、理解しにくい場合があります。そのため、違反の原因を表示できない場合に違反を非表示にするこのオプションが用意されています。
  • 疑わしいポイントごとに違反を 1 つだけ表示: 1 つの疑わしいポイントにつき、( 1 つのルールに対する) 1 つの違反だけをレポートします。たとえば、null 値のソースが複数ある null 間接参照の可能性が検出された場合、1 つの違反だけがレポートされます。このオプションを選択すると、 フロー解析のパフォーマンスが若干速くなります。

null チェック メソッド

[null チェック メソッド] オプションを指定すると、メソッドに null パラメーターが渡されたときに返す期待値を指定できます。そのため、偽陽性が減少するほか、null 変数の値が不明なときに通常作成される過剰なパスが減少します。

[有効] チェックボックスをオンにして、以下の情報を指定します。

  • 完全修飾型名(ワイルドカード): メソッドを含む型の完全修飾名を指定します。
  • メソッド名: メソッド名を指定します。
  • Null の場合の戻り値: メソッドに null パラメーターが渡されたときに返される値を指定します。
  • + サブクラスの定義: サブクラス中の null チェック メソッドの定義も、null チェック メソッドとして見なすかどうかを指定します。

null チェック メソッドの例

フロー解析は解析スコープでメソッドを解析します。たとえばサード パーティのライブラリなど、現在の解析スコープの外にメソッドがある場合、null チェック メソッドでパラメーターを指定する必要があります。この例のクラスは、異なるアセンブリに定義されており、解析スコープ (UString) の外にあります。このクラスには、Java の文字列があるコードをさまざまな方法で操作するための static メソッドがあります。その 1 つが UString.isEmptyOrNull(String) であり、これは以下のように定義されます。

public class UString
{
    static boolean isEmptyOrNull(String variable)
    {
        if ((variable == null) || (variable.length() == 0)) {
            return true;
        }
        return false;
    }
}

そして、フロー解析の ルール BD-EXCEPT-NP ルールによって解析される次のクラスがあります。

public class SomeClass
{
    void someMethod(String variable)
    {
        boolean flag = variable == null; // violation search starts here
        if (UString.isEmptyOrNull(variable)) {
            /** 
             * In case variable is null, we will always get to this branch of the if clause.
             */
            System.out.println("String is empty");
        } else {
            variable.toString(); // FALSE POSITIVE BD-EXCEPT-NP VIOLATION
        }
    }
}

フロー解析は メソッド isEmptyOrNull() の戻り値が不明であると仮定します。その理由は、このメソッドは解析スコープ中にないからです。フロー解析は if 文の then および else ブランチを解析し、それらの文の 1 つで違反を発見します。しかし、変数が null の場合、このメソッド呼び出しは true を返します。

null チェック メソッドのメソッド リストに UString.isEmptyOrNull() を追加して戻り値を指定することで、追跡された変数がこのメソッドに渡されたときにフロー解析は違反をレポートしなくなります。なぜなら、if 文の誤ったブランチが解析されず、その結果として偽陽性が回避されるからです。

null チェック メソッドの制限事項

null チェック メソッドのパラメーターに追加されるメソッドは、単純な Boolean 型の戻り値を持つ、static メソッドであるべきです。この制限事項は、パラメーター指定が複雑になり過ぎることを防ぎ、null チェック メソッドの結果に影響しかねない変数が他にないことを保証します。 

リソースの指定

[リソース] タブでは、BD.RES (リソース) カテゴリのルールを使ってチェックするリソースを定義することができます。BD.RES カテゴリのルールは、[リソース] タブで定義および有効化されているすべてのリソースについて、リソースが正しく使用されているかをチェックします。

  1. リソースのタイプを指定します。
  2. [有効] チェックボックスをオンにします。
  3. 適切な場合、[アプリケーション終了時の違反をレポートしない] オプションをオフにします。
  4. 矢印をクリックして [リソース アロケーター] および [リソース クローザー] タブを開き、表示されたテーブルにリソースのアロケーター/クローザーの情報を入力します。詳細については以下のセクションを参照してください。

リソース アロケーターの設定

[リソース アロケーター ] テーブルには、リソースを生成するメソッドの記述を入力できます。テーブルには以下の列があります。

  • 有効: 解析中にアロケーターを考慮するかどうかを指定します。
  • 完全修飾型名 (ワイルドカード): メソッドが宣言された型の完全修飾名です。任意の型で宣言された関数、また型の外で宣言されたグローバル関数を指定するには '*' を使用します。
  • メソッド名 (ワイルドカード): アロケーター メソッドの名前を指定します。任意の数の任意の文字を表すには '*' を使用します。
  • リソース パラメーター: メソッドが リソースを割り当てる1つ以上のパラメーターを指定します。パラメーターの位置 (1 から開始) を指定するか、アスタリスク (*) を指定して、すべてのパラメーターにリソースを割り当てます。
  • + サブクラスの定義: サブクラス中の (指定された名前の) アロケーター メソッドの定義も、アロケーター メソッドとして見なすかどうかを指定します。この設定は、インスタンス メソッドと非インスタンス メソッドの両方に適用されます。
  • "this" オブジェクトがリソース: メソッドが呼び出されたオブジェクトのリソースを割り当てることを示します。
  • リソース オブジェクトを返す: メソッドが割り当てられたリソースを返すことを示します。

一般的に、アロケーター メソッドはエラー コードを返してリソース割り当ての失敗を表します。アロケーターメソッドはリソースを返し、通常 NULL 値はリソース割り当ての失敗を表します。リソース リークを探すときに、フロー解析はリソースの割り当てが成功したか失敗したかを把握できる必要があります。これは、割り当てが実際に発生したパス上で発見されない割り当て解除メソッドへの呼び出しだけをフロー解析がレポートするのに役立ちます。リソース アロケーターメソッドがリソースを返し、NULL でない場合、フロー解析はリソースが正常に割り当てられたと推測します。

リソース クローザーの設定

[リソース クローザー] テーブルには、リソースをクローズするメソッドの記述を入力できます。テーブルには以下の列があります。

  • 有効: 解析中にクローザーを考慮するかどうかを指定します。
  • 完全修飾型名 (ワイルドカード): メソッドが宣言された型の完全修飾名です。任意の型で宣言された関数、または型の外で宣言されたグローバル関数を指定するには '*' を使用します。
  • メソッド名 (ワイルドカード): クローザー メソッドの名前を指定します。任意の数の任意の文字を表すには '*' を使用します。
  • + サブクラスの定義: サブクラス中の (指定された名前の) クローザー メソッドの定義も、クローザー メソッドとして見なすかどうかを指定します。この設定は、インスタンス メソッドと非インスタンス メソッドの両方に適用されます。
  • "this" オブジェクトが リソース: メソッドが呼び出されたオブジェクトのリソースをクローズすることを示します。
  • リソース パラメーター: メソッドが リソースをクローズする 1つ以上のパラメーターを指定します。パラメーターの位置 (1 から開始) を指定するか、アスタリスク (*) を指定して、すべてのパラメーターにリソースを割り当てます。

常に解析されるメソッドの指定

[常に解析すべきメソッド] オプションを使用すると、実行パス中で見つかったとき常に解析するメソッドを定義できます。これにより、特定のパスを解析したとき、通常は入らないメソッドを必ず解析するようにできます。

[有効] チェックボックスをオンにし、テーブルに以下の情報を入力します。

  • 完全修飾型名(ワイルドカード) メソッドを含む型の完全修飾名を指定します。
  • メソッド名: メソッド名を指定します。
  • + サブクラスの定義: サブクラス中のメソッドも考慮するかどうかを指定します。

インジェクション アノテーションの指定

[インジェクション アノテーション] オプションを使用すると、インジェクションに使用するアノテーションを定義できます。このオプションを指定すると、フィールド またはセッター メソッドにアノテーションがある場合、フロー解析はそのフィールド値は未初期化または null の可能性がないとみなします。

テーブルには以下の列があります。

  • 有効: 解析中にアノテーションを考慮するかどうかを指定します。
  • 完全修飾型名(ワイルドカード): アノテーションの完全修飾名を指定します。

Spring フレームワークを使用するプロジェクトの解析

Spring フレームワークを使用するプロジェクトを解析するのに特別な設定は必要ありません。  フロー解析は、Spring フレームワークの特徴を自動的に認識し、レポートされた違反を調整して正確な結果を表示します。

以下のセクションでは、フロー解析による Spring フレームワークの処理の詳細と、フロー解析ルールのレポートする違反への影響について説明します。

初期化されたフィールドの自動処理

フロー解析は、Spring インジェクションに使用されるアノテーションを識別します。アノテーションが付けられたフィールドは自動的に初期化されます。フィールド にアノテーションがある場合、フロー解析はそのフィールド値は未初期化または null の可能性がないとみなします。これにより、以下のルールが違反を誤検出するのを防ぎます。

  • BD-PB-CC - 常に同じ値に評価される条件式を避ける
  • BD-PB-NOTEXPLINIT - 明示的に初期化する前の使用を避ける
  • BD-EXCEPT-NP - NullPointerException を避ける

フィールドを自動的に初期化するインジェクション アノテーションのデフォルトのリストを参照したり、テスト コンフィギュレーションを編集することでリストをカスタマイズできます ([静的解析の設定] > [制御フレームワークの置換の設定])。

コントローラ― クラスの処理

フロー解析は、Spring コントローラー クラスおよび HTTP リクエスト処理メソッドが使用されているかを識別できます。結果として、以下のことが可能です。

  • BD.SECURITY.TDRESP ルールは、HTTP リクエスト処理メソッドから返された汚染されている可能性があるデータが検証されていない場合、違反をレポートします。
  • 汚染されたデータを検出するルールは、危険なメソッドに渡された HTTP リクエスト パラメーターが検証されていない場合、違反をレポートします。

フロー解析は、以下のアノテーションのいずれかを持つメソッドは HTTP リクエスト処理メソッドであるとみなします。

  • @RequestMapping(method = RequestMethod.GET)
  • @RequestMapping(method = RequestMethod.HEAD)
  • @RequestMapping(method = RequestMethod.PUT)
  • @RequestMapping(method = RequestMethod.POST)
  • @RequestMapping(method = RequestMethod.DELETE)
  • @RequestMapping(method = RequestMethod.PATCH)
  • @GetMapping
  • @PutMapping
  • @PostMapping
  • @DeleteMapping
  • @PatchMapping
  • @ExceptionHandler

フロー解析は、以下のメソッド パラメーター アノテーションは HTTP リクエスト パラメーター (汚染されている可能性があるデータのソース) を定義すると仮定します。

  • org.springframework.web.bind.annotation.RequestParam
  • org.springframework.web.bind.annotation.ModelAttribute
  • org.springframework.web.bind.annotation.PathVariable
  • org.springframework.web.bind.annotation.RequestBody

(info) フロー解析は、Java Validation API は汚染されたデータの適切な検証を確実に行うには十分でないと見なします。Java Validation は、多くの場合、外部ソースから取得したデータを検証するのに使用されますが、汚染されたデータは、特定のコンテキストで使用する前に適切にサニタイズされる必要があります。つまり、適切な検証を行うには、データが SQL クエリーに渡されるのか、HTTP レスポンスに埋め込まれるのかに応じて、異なる検証メソッドを使用する必要があるということです。

汚染されたデータ ソースの識別

フロー解析は、Spring 特有の汚染された可能性があるデータのソースを認識できます。汚染されたデータを検出するフロー解析ルールは、以下のソースから取得したデータが検証せずに危険なメソッドに渡されている場合、違反をレポートします。

  • Spring 環境プロパティ (org.springframework.core.env.PropertyResolver)
  • Spring HTTP リクエスト (org.springframework.web.context.request.WebRequest)
  • Spring-specific Database インターフェイス (org.springframework.jdbc クラス)
  • Spring-specific JMS (Java Message Service) クラス (org.springframework.jms.core.JmsTemplate)


  • No labels