(57)【特許請求の範囲】
【請求項１】
リソースを捕捉するリソース捕捉関数と前記リソースを解放するリソース解放関数をソースコードから抽出するプログラム解析装置であって、
ソースコードを入力する入力手段と、
前記ソースコードに現れる異なる２つの第１関数と第２関数を選択し、ソースコード上で前記第１関数が呼び出された位置から辿ることのできる実行経路の全てにおいて、前記第１関数の返却値を格納する変数の参照状況と前記第２関数の呼出し状況が一般的なリソース格納変数と一般的なリソース解放関数の用いられ方に当てはまる場合は、前記第１関数と前記第２関数のそれぞれをリソース捕捉関数とリソース解放関数として抽出する抽出手段と、を有し、
前記一般的なリソース格納変数と一般的なリソース解放関数の用いられ方は、リソース捕捉関数が呼び出された後の実行経路において前記リソース解放関数の呼出し回数は１回以内であって、前記実行経路において前記リソース解放関数が呼び出されないときは、前記実行経路には前記リソース捕捉関数が呼び出された後に分岐があり、当該分岐の後は前記リソース格納変数が参照されていないものであり、前記実行経路において前記リソース解放関数が呼び出されているときは、前記リソース解放関数が呼び出された後の分岐の合流後は前記リソース格納変数が参照されていないことを特徴とするプログラム解析装置。
【請求項２】
請求項１に記載のプログラム解析装置と、
前記プログラム解析装置が抽出したリソース捕捉関数により捕捉されたリソースが未初期化のまま参照されている箇所をソースコード上で検出する検出手段と、
を有することを特徴とする誤り検出装置。
【請求項３】
リソースを捕捉するリソース捕捉関数と前記リソースを解放するリソース解放関数をソースコードから抽出する、コンピュータにより実行されるプログラム解析方法であって、
ソースコードを入力するステップと、
前記ソースコードに現れる異なる２つの第１関数と第２関数を選択し、ソースコード上で前記第１関数が呼び出された位置から辿ることのできる実行経路の全てにおいて、前記第１関数の返却値を格納する変数の参照状況と前記第２関数の呼出し状況が一般的なリソース格納変数と一般的なリソース解放関数の用いられ方に当てはまる場合は、前記第１関数と前記第２関数のそれぞれをリソース捕捉関数とリソース解放関数として抽出するステップと、を有し、
前記一般的なリソース格納変数と一般的なリソース解放関数の用いられ方は、リソース捕捉関数が呼び出された後の実行経路において前記リソース解放関数の呼出し回数は１回以内であって、前記実行経路において前記リソース解放関数が呼び出されないときは、前記実行経路には前記リソース捕捉関数が呼び出された後に分岐があり、当該分岐の後は前記リソース格納変数が参照されていないものであり、前記実行経路において前記リソース解放関数が呼び出されているときは、前記リソース解放関数が呼び出された後の分岐の合流後は前記リソース格納変数が参照されていないことを特徴とするプログラム解析方法。
【請求項４】
コンピュータにより実行される誤り検出方法であって、
請求項３に記載のプログラム解析方法によりリソース捕捉関数を抽出するステップと、
前記リソース捕捉関数により捕捉されたリソースが未初期化のまま参照されている箇所をソースコード上で検出するステップと、
を有することを特徴とする誤り検出方法。
【請求項５】
請求項１に記載のプログラム解析装置の各手段としてコンピュータを動作させることを特徴とするプログラム解析プログラム。
【請求項６】
請求項２に記載の誤り検出装置の各手段としてコンピュータを動作させることを特徴とする誤り検出プログラム。
【発明の詳細な説明】
【技術分野】
【０００１】
本発明は、ソースコードを静的に解析する技術に関する。
【背景技術】
【０００２】
プログラム作成時に誤りを検出する技術が研究されている。そのひとつに、静的コード解析によりプログラムの誤りの可能性のある箇所を検出する技術がある。
【０００３】
静的コード解析による誤り検出技術の例として、Ｃプログラムを対象としたｍａｌｌｏｃ関数で確保したメモリがｆｒｅｅ関数で解放されてない箇所を検出する技術、ｍａｌｌｏｃ関数で確保した未初期化メモリを参照している箇所を検出する技術などがある（例えば非特許文献１参照）。
【先行技術文献】
【非特許文献】
【０００４】
【非特許文献１】W. R. Bush, J. D. Pincus, and D. J. Sielaff, "A static analyzer for finding dynamic programming errors", Software Practice and Experience, 2000年, vol. 30, No. 7, pp. 775-802
【発明の概要】
【発明が解決しようとする課題】
【０００５】
ｍａｌｌｏｃ関数やｆｒｅｅ関数などの一般的なリソース捕捉関数、リソース解放関数を使用するだけでなく、独自のリソース捕捉関数とリソース解放関数を作成することがある。
【０００６】
この場合、既存の静的コード解析ツールでは、ｍａｌｌｏｃ関数やｆｒｅｅ関数などの一般的な関数で捕捉したリソースの未初期化参照は検出できても、ユーザが定義した独自のリソース捕捉関数を用いて捕捉された独自のリソースの未初期化参照を検出することはできないという問題があった。
【０００７】
既存の静的コード解析ツールに、ユーザが定義したリソース捕捉関数やリソース解放関数を登録し、ｍａｌｌｏｃ関数やｆｒｅｅ関数と同等に静的コード解析をする機能を追加することで、ユーザが定義したリソース捕捉関数についても未初期化参照の誤りを検出できると考えられる。
【０００８】
そのためには、ユーザがリソース捕捉・解放関数を管理し、静的コード解析ツールに登録する作業が必要となる。
【０００９】
本発明は、上記に鑑みてなされたものであり、ユーザが、ユーザの定義したリソース捕捉・解放関数を管理せずにプログラムのソースコードを解析することによりプログラム中で用いられているリソース捕捉関数やリソース解放関数を抽出し、リソース捕捉関数の使い方の誤りを検出することを目的とする。
【課題を解決するための手段】
【００１０】
第１の本発明に係るプログラム解析装置は、リソースを捕捉するリソース捕捉関数と前記リソースを解放するリソース解放関数をソースコードから抽出するプログラム解析装置であって、ソースコードを入力する入力手段と、前記ソースコードに現れる異なる２つの第１関数と第２関数を選択し、ソースコード上で前記第１関数が呼び出された位置から辿ることのできる実行経路の全てにおいて、前記第１関数の返却値を格納する変数の参照状況と前記第２関数の呼出し状況が一般的なリソース格納変数と一般的なリソース解放関数の用いられ方に当てはまる場合は、前記第１関数と前記第２関数のそれぞれをリソース捕捉関数とリソース解放関数として抽出する抽出手段と、を有し、前記一般的なリソース格納変数と一般的なリソース解放関数の用いられ方は、リソース捕捉関数が呼び出された後の実行経路において前記リソース解放関数の呼出し回数は１回以内であって、前記実行経路において前記リソース解放関数が呼び出されないときは、前記実行経路には前記リソース捕捉関数が呼び出された後に分岐があり、当該分岐の後は前記リソース格納変数が参照されていないものであり、前記実行経路において前記リソース解放関数が呼び出されているときは、前記リソース解放関数が呼び出された後の分岐の合流後は前記リソース格納変数が参照されていないことを特徴とする。
【００１２】
第２の本発明に係る誤り検出装置は、第１の本発明に係るプログラム解析装置と、前記プログラム解析装置が抽出したリソース捕捉関数により捕捉されたリソースが未初期化のまま参照されている箇所をソースコード上で検出する検出手段と、を有することを特徴とする。
【００１３】
第３の本発明に係るプログラム解析方法は、リソースを捕捉するリソース捕捉関数と前記リソースを解放するリソース解放関数をソースコードから抽出する、コンピュータにより実行されるプログラム解析方法であって、ソースコードを入力するステップと、前記ソースコードに現れる異なる２つの第１関数と第２関数を選択し、ソースコード上で前記第１関数が呼び出された位置から辿ることのできる実行経路の全てにおいて、前記第１関数の返却値を格納する変数の参照状況と前記第２関数の呼出し状況が一般的なリソース格納変数と一般的なリソース解放関数の用いられ方に当てはまる場合は、前記第１関数と前記第２関数のそれぞれをリソース捕捉関数とリソース解放関数として抽出するステップと、を有し、前記一般的なリソース格納変数と一般的なリソース解放関数の用いられ方は、リソース捕捉関数が呼び出された後の実行経路において前記リソース解放関数の呼出し回数は１回以内であって、前記実行経路において前記リソース解放関数が呼び出されないときは、前記実行経路には前記リソース捕捉関数が呼び出された後に分岐があり、当該分岐の後は前記リソース格納変数が参照されていないものであり、前記実行経路において前記リソース解放関数が呼び出されているときは、前記リソース解放関数が呼び出された後の分岐の合流後は前記リソース格納変数が参照されていないことを特徴とする。
【００１５】
第４の本発明に係る誤り検出方法は、コンピュータにより実行される誤り検出方法であって、第３の本発明に係るプログラム解析方法によりリソース捕捉関数を抽出するステップと、前記リソース捕捉関数により捕捉されたリソースが未初期化のまま参照されている箇所をソースコード上で検出するステップと、を有することを特徴とする。
【００１６】
第５の本発明に係るプログラム解析プログラムは、第１の本発明に係るプログラム解析装置の各手段としてコンピュータを動作させることを特徴とする。
【００１７】
第６の本発明に係る誤り検出プログラムは、第２の本発明に係る誤り検出装置の各手段としてコンピュータを動作させることを特徴とする。
【発明の効果】
【００１８】
本発明によれば、ユーザが、ユーザの定義したリソース捕捉・解放関数を管理せずにプログラムのソースコードを解析することによりプログラム中で用いられているリソース捕捉関数の使い方の誤りを検出することができる。
【図面の簡単な説明】
【００１９】
【図１】本実施の形態におけるソースコード検査装置の構成を示す機能ブロック図である。
【図２】本実施の形態におけるソースコード検査装置の処理の流れを示すフローチャートである。
【図３】ソースコードの解析処理の流れを示すフローチャートである。
【図４】ソースコード検査装置が入力するソースコードの例を示す図である。
【図５】図４のソースコードから作成したサブルーチン展開コードの例を示す図である。
【図６】図５のサブルーチン展開コードから抽出した関数一覧を示す図である。
【図７】図５のサブルーチン展開コードから作成した制御フローグラフである。
【図８Ａ】図５のサブルーチン展開コードの解析結果を示す図である。
【図８Ｂ】図８Ａに続く、図５のサブルーチン展開コードの解析結果を示す図である。
【図８Ｃ】図８Ｂに続く、図５のサブルーチン展開コードの解析結果を示す図である。
【図９】本実施の形態で用いるリソース捕捉関数とリソース解放関数とリソース格納変数の出現パタンを説明する図である。
【図１０】リソース捕捉関数とリソース解放関数の抽出処理の流れを示すフローチャートである。
【図１１】２つの関数と変数がリソース捕捉関数、リソース解放関数、およびリソース格納変数の出現パタンに当てはまるか否かを調べる処理の流れを示すフローチャートである。
【発明を実施するための形態】
【００２０】
以下、本発明の実施の形態について図面を用いて説明する。
【００２１】
図１は、本実施の形態におけるソースコード検査装置１の構成を示す機能ブロック図である。本ソースコード検査装置１は、ソースコードを入力して解析し、未初期化リソースを参照している誤りを検出する装置である。
【００２２】
図１に示すソースコード検査装置１は、入力部１１、解析部１２、抽出部１３、および検出部１４を備える。ソースコード検査装置１が備える各部は、演算処理装置、記憶装置等を備えたコンピュータにより構成して、各部の処理がプログラムによって実行されるものとしてもよい。このプログラムはソースコード検査装置１が備える記憶装置に記憶されており、磁気ディスク、光ディスク、半導体メモリ等の記録媒体に記録することも、ネットワークを通して提供することも可能である。以下、各部について説明する。
【００２３】
入力部１１は、検査対象のソースコードを入力する。後述の実施例では、Ｃ言語のソースコードを入力する例で説明するが、Ｃ言語のみに限らず、他のプログラミング言語にも適用できる。
【００２４】
解析部１２は、入力部１１が入力したソースコードを解析する。具体的には、解析部１２は、ソースコード中でサブルーチン呼出し（関数呼出し）している箇所に、そのサブルーチン（関数）の定義コードを書き足してサブルーチン展開コードを作成し、サブルーチン展開コードの各行について、関数呼出しをしているか、関数の返却値を格納する変数はなにか、関数の引数はなにか、分岐しているか、分岐後の合流地点はどこか、利用されている変数はなにか、などの情報を解析する。また、解析部１２は、サブルーチン展開コードの各行をノードとした制御フローグラフを作成する。
【００２５】
抽出部１３は、解析部１２の解析結果を元に、リソース捕捉関数とリソース解放関数のペアを抽出する。具体的には、ソースコード中の２つの異なる関数について、リソース捕捉関数とリソース解放関数が使われるパタンに合致するか否かを調べ、ソースコードの中からリソース捕捉関数とリソース解放関数のペアを抽出する。例えば、リソース捕捉関数とリソース解放関数が使われるパタンとしては、リソース捕捉関数が呼出されて、その結果がリソース格納変数に代入され、リソース格納変数を介してリソースが使われた後で、リソース解放関数が呼出されるパタンがある。この場合、リソース捕捉関数が呼出された後にリソース格納変数が参照される。リソース解放関数より後にリソース格納変数が参照されることもない。また、リソース捕捉関数が呼出された後にリソース解放関数が呼出されるが、リソース解放関数が２回以上呼出されることはない。後述する実施例では、リソース捕捉関数及びリソース解放関数のエラー処理を考慮したパタンを用いてリソース捕捉関数とリソース解放関数のペアを抽出する。
【００２６】
検出部１４は、抽出部１３が抽出したリソース捕捉関数が返す未初期化リソースを参照している箇所を検出する。既存の静的コード解析ツールでは、ｍａｌｌｏｃやｎｅｗなどの一般的なリソース捕捉関数で捕捉したリソースの未初期化参照を解析できる。既存の静的コード解析ツールに、抽出部１３が抽出したリソース捕捉関数及びリソース解放関数のペアを登録することで検出部１４を実現する。未初期化リソースの参照を検出する方法としては、例えば非特許文献１に記載されている未初期化メモリの参照を検出する方法を用いることができる。
【００２７】
次に、本実施の形態におけるソースコード検査装置１の動作について説明する。
【００２８】
図２は、本実施の形態におけるソースコード検査装置１の処理の流れを示すフローチャートである。
【００２９】
入力部１１が検査対象のソースコードを入力する（ステップＳ１）。
【００３０】
解析部１２がソースコードを解析する（ステップＳ２）。ソースコードの解析処理の詳細については後述する。
【００３１】
抽出部１３が、ソースコードの解析結果を元に、リソース捕捉関数とリソース解放関数のペアをソースコードから抽出する（ステップＳ３）。リソース捕捉関数とリソース解放関数の抽出処理の詳細については後述する。
【００３２】
そして、検出部１４が、一般的なリソース捕捉関数に加えて、抽出部１３の抽出したリソース捕捉関数が捕捉したリソースも含めて、未初期化リソースを参照している箇所を検出する（ステップＳ４）。
【００３３】
（ソースコードの解析処理）
次に、ソースコードの解析処理について説明する。
【００３４】
図３は、ソースコードの解析処理の流れを示すフローチャートである。以下では、図４に示すソースコードを入力した具体例とともにソースコードの解析処理を説明する。
【００３５】
解析部１２は、入力部１１が入力したソースコードからサブルーチン展開コードを作成する（ステップＳ２１）。図５に、図４のソースコードから作成したサブルーチン展開コードの例を示す。図５の例では、解析部１２は、ｍａｉｎ関数から呼び出されているｆｉｎｉｓｈ関数とａｂｏｒｔ＿ｐｒｏｇｒａｍ関数のソースコードを呼び出した箇所の下に展開して追記している。解析部１２は、さらにｆｉｎｉｓｈ関数から呼び出されているａｂｏｒｔ＿ｐｒｏｇｒａｍ関数も展開して追記している。具体的には、符号１０１Ａ，１０１Ｂ，１０１Ｃで示す箇所にａｂｏｒｔ＿ｐｒｏｇｒａｍ関数を展開し、符号１０２で示す箇所にｆｉｎｉｓｈ関数を展開した。符号１０１Ｂ，１０１Ｃで示す箇所に展開したａｂｏｒｔ＿ｐｒｏｇｒａｍ関数はｆｉｎｉｓｈ関数から呼び出されたものである。
【００３６】
サブルーチン展開コードでは、関数を展開した箇所の行番号として、呼び出し元の行番号に元々のソースコードの行番号を付与した行番号（以下、「コールスタック付き行番号」と称する）を付与する。例えば、符号１０１Ａで示した箇所のａｂｏｒｔ＿ｐｒｏｇｒａｍ関数は、ｍａｉｎ関数の９行目で呼び出されており、ａｂｏｒｔ＿ｐｒｏｇｒａｍ関数は、図４のソースコードの２８−３０行目に記述されているので、９行目に展開したａｂｏｒｔ＿ｐｒｏｇｒａｍ関数の各行に行番号９−２８，９−２９，９−３０を付与する。別の例では、符号１０２で示した箇所のｆｉｎｉｓｈ関数はｍａｉｎ関数の１３行目で呼び出されており、符号１０１Ｂで示した箇所のａｂｏｒｔ＿ｐｒｏｇｒａｍ関数はｆｉｎｉｓｈ関数の２３行目で呼び出されているので、符号１０１Ｂで示した箇所のａｂｏｒｔ＿ｐｒｏｇｒａｍ関数の各行に行番号１３−２３−２８，１３−２３−２９，１３−２３−３０を付与する。
【００３７】
続いて、解析部１２は、サブルーチン展開コードから関数を抽出して関数一覧を作成する（ステップＳ２２）。図６に、図５のサブルーチン展開コードから抽出した関数一覧を示す。解析部１２は、抽出した関数に関数ＩＤを付与する。
【００３８】
続いて、解析部１２は、サブルーチン展開コードから制御フローグラフを作成する（ステップＳ２３）。制御フローグラフは、プログラムを実行したときの制御の流れを有向グラフで表したものである。図７に、図５のサブルーチン展開コードから作成した制御フローグラフを示す。本実施の形態では、コールスタック付き行番号をノードとし、呼び出された関数の内部に制御の流れを追うステップイン接続と、関数の内部に制御の流れを追わないステップオーバー接続の２つのエッジを付与した。図７の点線で示すエッジがステップイン接続を示し、実線で示すエッジがステップオーバー接続を示す。なお、本実施の形態では、プログラムの制御構造のひとつであるループは考慮せずに、ループは、１回だけ実行されるものとみなして解析する。
【００３９】
そして、解析部１２は、サブルーチン展開コードを解析する（ステップＳ２４）。図８Ａ〜８Ｃは、解析部１２によるサブルーチン展開コードの解析結果を示す図である。本実施の形態では、サブルーチン展開コードの行ごとに、エイリアス集合、関数呼出し、関数ＩＤ、関数返却値格納変数、引数、分岐、合流行番号、および効果有り参照されている変数を抽出する。
【００４０】
エイリアス集合は、ソースコードに現れる変数のエイリアス組の集合である。本実施の形態では、該当行を実行後の時点でのエイリアス集合を求めている。例えば、４行目のｃｍｄと５行目のｃｍｄは同じものであるので、行番号と変数名をペアにしたフロー依存変数（４，ｃｍｄ），（５，ｃｍｄ）をエイリアス集合に加えている。エイリアス集合の要素は、変数名が異なるときも同じものとみなすことができる。属するエイリアス集合が異なるときは異なる変数とみなすことができる。本実施の形態で想定するエイリアス解析はフローセンシティブエイリアス解析であり、ソースコードの行によって変数の関係性が変わることを考慮するものである。なお、フロー依存変数とは、変数名rと変数が出現したコールスタック付き行番号kの組(k, r)である。
【００４１】
関数呼出しは、当該行で関数を呼び出しているか否かを示す。関数を呼び出しているときは、呼び出している関数のＩＤ、呼び出している関数の返却値を格納する変数、および関数の引数を記載する。ソースコード上で関数に渡されている引数がアドレス演算子（＆）や間接演算子（＊）で修飾されている変数の場合は、これらの演算子を外した変数も解析結果の引数に記載する。なぜならば、アドレス演算子や間接演算子で修飾された変数が参照される前に、アドレス演算子や間接演算子で修飾されていない変数の値が参照されるからである。例えば、ソースコード上で関数に渡されている引数が＆ａの場合は、解析結果の引数の項目には、＆ａとａを記載する。別の例では、ソースコード上で関数に渡されている引数が＊＊ａの場合は、解析結果の引数の項目には、＊＊ａと＊ａとａを記載する。
【００４２】
分岐は、当該行が分岐であるか否かを示す。分岐があるときは分岐したルートの合流先を合流行番号に記載する。ｉｆ文の分岐では、ｔｈｅｎ節とｅｌｓｅ節に実行経路が分岐するが、ｔｈｅｎ節とｅｌｓｅ節の後の行が合流先となる。
【００４３】
効果有り参照されている変数は、当該行で実質的に使われている変数を記載する。より具体的には、変数ｖが効果有り参照されるとは、次に示すいずれかの条件を満たす場合であると定義する。
【００４４】
（１）変数ｖの値が読み取られ、かつ、別の変数ｗに値が代入され、その結果、変数ｖと変数ｗがエイリアスの関係にならない
（２）変数ｖが関数の引数として参照される
（３）変数ｖが条件判定文の条件式の中で参照される
【００４５】
以下、効果有り参照されている変数の具体例を説明する。例えば、ａ＝ｖと記載された行を考えると、この行を実行した結果、変数ａは変数ｖのエイリアスになるので、この行では変数ｖは効果有り参照されていない。別の例で、ａ＝ｖ＋１が記載された行を考えると、変数ｖの値が読み取られ、かつ、変数ａに値がセットされ、その結果、変数ａと変数ｖはエイリアスの関係にならないので、この行では変数ｖは効果有り参照されている。さらに、この行の変数ａについて考えると、変数ａの値は参照されていないので、変数ａは効果有り参照されていない。
【００４６】
また別の例で、＊ｖ＝ａ＋１が記載された行を考えると、変数ｖの値が参照され、デリファレンスされて変数＊ｖに値が格納されていて、その結果、変数ｖと変数＊ｖはエイリアスの関係にならないので、変数ｖは効果有り参照されている。さらに別の例で、ａ＝＆ｖが記載された行を考えると、変数ｖのアドレスは参照されているが変数ｖの値は参照されていないので、変数ｖは効果有り参照されていない。
【００４７】
条件式の中で参照される例を挙げると、例えばｉｆ（ｖ）｛・・・｝が記載された行では、条件判定文の条件式の中で変数ｖの値が参照されているので、変数ｖは効果有り参照されている。
【００４８】
（リソース捕捉関数とリソース解放関数の抽出処理）
次に、リソース捕捉関数とリソース解放関数の抽出処理について説明する。
【００４９】
ソースコード中の一般的なリソース捕捉関数と一般的なリソース解放関数の出現パタンとしては、例えば最もシンプルなパタンとして、リソース捕捉関数の返却値を格納する変数（リソース格納変数）が指定されてリソース捕捉関数が呼び出された後、リソース格納変数が指示するリソースが使用され、その後リソース解放関数が１回だけ呼び出されるパタンがある。リソース格納変数は、リソース捕捉関数の前とリソース解放関数の後に使用されることはない。このような出現パタンに当てはまる２つの関数はリソース捕捉関数とリソース解放関数の可能性があると推定できる。
【００５０】
本実施の形態では、リソース捕捉関数のエラー処理とリソース解放関数のエラー処理も含めたパタンに当てはまる２つの関数をリソース捕捉関数とリソース解放関数として抽出する。
【００５１】
図９は、本実施の形態で用いるリソース捕捉関数とリソース解放関数とリソース格納変数の出現パタンを説明する図である。図９に示すパタンは、リソース捕捉関数の後にエラー処理があり、リソース解放関数の後にエラー処理があるパタンである。リソース捕捉関数の後のエラー処理内では、リソース格納変数が参照されることはなく、リソース解放関数が呼び出されずに処理を抜ける。また、リソース解放関数の後のエラー処理内では、ログ出力などでリソース格納変数が参照されることがあるが、エラー処理を抜けた後にリソース格納変数が参照されることはない。
【００５２】
抽出部１３は、解析部１２の解析結果を元に、関数一覧の全ての２つの関数の組み合わせについて、リソース格納変数を推定し、２つの関数とリソース格納変数の出現パタンが図９に示した、リソース捕捉関数とリソース解放関数とリソース格納変数の出現パタンに当てはまるか否かを調べて、パタンに当てはまる場合は、２つの関数がリソース捕捉関数とリソース解放関数であるとして抽出する。以下、リソース捕捉関数とリソース解放関数の抽出処理の流れについて説明する。
【００５３】
図１０，１１は、リソース捕捉関数とリソース解放関数の抽出処理の流れを示すフローチャートである。
【００５４】
まず、抽出部１３は、リソース捕捉関数とリソース解放関数のペアを格納する関数ペア集合を空集合にする（ステップＳ３１）。
【００５５】
抽出部１３は、関数一覧から２つの関数ｆ，ｇを選択し、全ての関数の組み合わせについて以下の処理を繰り返す（ステップＳ３２）。関数一覧に含まれる関数ＩＤの集合をＦとするとｆ∈Ｆ，ｇ∈Ｆ，ｆ≠ｇである。以下の処理では、関数ｆがリソース捕捉関数であるか、関数ｇがリソース解放関数であるかを調べる。
【００５６】
抽出部１３は、解析結果を参照し、関数ｆが呼び出されている行番号ｋを挙げて行番号集合Ｋを作成する（ステップＳ３３）。
【００５７】
抽出部１３は、解析結果を参照し、行番号ｋ∈Ｋと行番号ｋにおいて関数ｆの返却値を格納している変数ｒのペアをフロー依存変数（ｋ，ｒ）としてフロー依存変数集合Ｒを作成する（ステップＳ３４）。この処理により、関数ｆが呼び出されている行番号ｋとリソース格納変数の候補である変数ｒをペアとしたフロー依存変数集合Ｒ＝｛（ｋ１，ｒ１），（ｋ２，ｒ２），・・・｝が作成される。
【００５８】
抽出部１３は、好適パタン数を０に設定し、全てのフロー依存変数（ｋ，ｒ）∈Ｒについて、行番号ｋ以降の実行経路において、２つの関数ｆ，ｇと変数ｒの出現パタンが図９に示したパタンに当てはまるか否か判定する（ステップＳ３５−Ｓ３７）。ステップＳ３６の判定結果がポジティブであるときは好適パタン数に１加算する。２つの関数ｆ，ｇと変数ｒの出現パタンが図９に示したパタンに当てはまるか否か判定する処理の詳細は後述する。
【００５９】
そして、全てのフロー依存変数（ｋ，ｒ）∈Ｒの判定結果がポジティブであるときは、関数ｆ，ｇはリソース捕捉関数とリソース解放関数であるとして、関数ペア（ｆ，ｇ）を関数ペア集合に追加する（ステップＳ３８）。フロー依存変数の数｜Ｒ｜と好適パタン数が一致するときは全てのフロー依存変数の判定結果がポジティブであるので、関数ペア（ｆ，ｇ）を関数ペア集合に追加する。ただし、行番号ｋの数｜Ｋ｜とフロー依存変数の数｜Ｒ｜が一致しない場合は、ソースコード中に関数ｆの返却値が変数に格納されない箇所があり、関数ｆはリソース捕捉関数ではないので、関数ペア（ｆ，ｇ）を関数ペア集合に追加しない。
【００６０】
抽出部１３は、全ての関数ペア（ｆ，ｇ），ｆ∈Ｆ，ｇ∈Ｆ，ｆ≠ｇについて、ステップＳ３３〜Ｓ３８の処理を行う（ステップＳ３９）。
【００６１】
以上の処理により、リソース捕捉関数とリソース解放関数のペアである可能性の関数ペアが関数ペア集合に格納される。
【００６２】
続いて、２つの関数ｆ，ｇと変数ｒの出現パタンが図９に示したパタンに当てはまるか否か判定する処理の詳細について説明する。
【００６３】
図１１は、２つの関数ｆ，ｇと変数ｒがリソース捕捉関数、リソース解放関数、およびリソース格納変数の出現パタンに当てはまるか否かを調べる処理の流れを示すフローチャートである。図１１に示す処理では、関数ｆが呼び出された行番号ｋより後の実行経路の全てにおいて、関数ｆ，ｇと変数ｒの出現パタンが図９に示したパタンに当てはまるか否かを判定する。
【００６４】
抽出部１３は、制御フローグラフを参照し、関数ｆが呼び出された行番号ｋより後の実行経路ｐを全て挙げて実行経路集合Ｐを作成する（ステップＳ５１）。ここで、実行経路ｐを作成する際には、関数ｆ，ｇへのステップイン接続はたどらない。関数ｆ，ｇ以外の関数へのステップイン接続がある場合はステップイン接続だけをたどる。１ノードを起点とするステップオーバー接続が複数ある場合には、接続の選び方に応じた実行経路をそれぞれ作成する。実行経路ｐは、コールスタック付き行番号の順序付き集合ｐ＝｛ｎ１，ｎ２，・・・，ｎｍ｝で表す。
【００６５】
抽出部１３は、好適経路数、捕捉失敗候補経路数を０に設定し、全ての実行経路ｐ∈Ｐについて、以下の処理を繰り返す（ステップＳ５２）。好適経路数は実行経路集合Ｐのなかで図９のパタンに当てはまった実行経路ｐの数を示す。捕捉失敗候補経路数はリソース捕捉関数のエラー処理に当てはまった実行経路ｐの数を示す。
【００６６】
抽出部１３は、補足後使用区間調査フラグをｔｒｕｅに設定する（ステップＳ５３）。補足後使用区間調査フラグは、実行経路ｐの検査結果を示すフラグであり、実行経路ｐが図９のパタンに当てはまらないときはｆａｌｓｅが設定される。
【００６７】
抽出部１３は、実行経路ｐ上で関数ｇが２回以上呼び出されているか判定する（ステップＳ５４）。リソース解放関数が２回以上呼び出されることはないので、関数ｇが２回以上呼び出されている場合は（ステップＳ５４のＹＥＳ）、補足後使用区間調査フラグをｆａｌｓｅに設定する（ステップＳ６０）。
【００６８】
抽出部１３は、実行経路ｐ上で関数ｇが１回呼び出されているか判定する（ステップＳ５５）。関数ｇが呼び出されていない場合は（ステップＳ５５のＮＯ）、実行経路ｐはリソース捕捉関数のエラー処理の経路である可能性があるのでステップＳ５８に進む。
【００６９】
実行経路ｐ上で関数ｇが１回呼び出されている場合（ステップＳ５５のＹＥＳ）、抽出部１３は、関数ｇが呼び出されるまでに変数ｒが使用されているか判定する（ステップＳ５６）。変数ｒが使用されていない場合は（ステップＳ５６のＮＯ）、補足後使用区間調査フラグをｆａｌｓｅに設定する（ステップＳ６０）。
【００７０】
なお、「変数ｒが使用される」とは、具体的には、「フロー依存変数（ｋ，ｒ）のエイリアスのいずれかが効果有り参照される」という意味である。記述を簡潔にするために、本実施例では「変数rが使用される」と記述することにする。
【００７１】
ここで、ステップＳ５６の変数ｒの使用判定について説明する。関数ｇは実行経路ｐのｊ番目の要素ｎｊに対応する行で呼び出されているとする。抽出部１３は、実行経路ｐの先頭の要素ｎ１からｊ−１番目の要素ｎｊ−１までのいずれかの要素において、解析結果の効果有り参照されている変数の項目に変数ｒのエイリアスのいずれかが記載されているか否かを調べる。変数ｒのエイリアスが効果有り参照されている場合はステップＳ５６の判定結果はＹＥＳとなり、変数ｒのエイリアスが効果有り参照されていない場合はステップＳ５６の判定結果はＮＯとなる。
【００７２】
関数ｇが呼び出されるまでに変数ｒが使用されている場合（ステップＳ５６のＹＥＳ）、抽出部１３は、関数ｇが呼び出された後、変数ｒが使用されているか判定する（ステップＳ５７）。変数ｒが使用されている場合は（ステップＳ５７のＹＥＳ）、補足後使用区間調査フラグをｆａｌｓｅに設定する（ステップＳ６０）。
【００７３】
ただし、リソース解放関数のエラー処理の経路では、関数ｇが呼び出された後も変数ｒが使用される可能性があるので、リソース解放関数のエラー処理と思われる箇所は飛ばして判定する。具体的には、抽出部１３は、実行経路ｐの中で、要素ｎｊの後に、要素ｎｊと同階層で最初に出現する分岐を探し、分岐が存在する場合は実行経路ｐの中でその分岐の合流先である要素ｎｈ以降の要素をステップＳ５７の判定対象とする。また、分岐が存在しない場合や分岐の途中でプログラムが終了するなどの理由で合流先が存在しない場合は、実行経路ｐの中で要素ｎｊの後に要素ｎｊと同階層で出現する要素ｎｈ以降をステップＳ５７の判定対象とする。なお、実行経路ｐの中に関数ｇが呼び出された要素ｎｊより後で要素ｎｊと同階層の要素がない場合は、ステップＳ５７の判定結果をＮＯとしてステップＳ６１に進む。
【００７４】
一方、実行経路ｐ上で関数ｇが呼び出されていない場合の（ステップＳ５５のＮＯ）、実行経路ｐがリソース捕捉関数のエラー処理の経路であるか否かの判定は、実行経路ｐで変数ｒが使用されているか判定することで行う（ステップＳ５８）。具体的には、実行経路ｐの中で、先頭の要素ｎ１の後に、要素ｎ１と同階層で最初に出現する分岐を探し、分岐が存在する場合は、分岐が出現する要素を要素ｎｈ’とし、分岐が存在しない場合は、要素ｎ１を要素ｎｈ’とする。そして、実行経路ｐの要素ｎｈ’の次の要素から最後の要素ｎｍまでのいずれかの要素に対応する箇所で、変数ｒが使用されているか調べる。
【００７５】
変数ｒが使用されている場合は（ステップＳ５８のＹＥＳ）、補足後使用区間調査フラグをｆａｌｓｅに設定する（ステップＳ６０）。
【００７６】
変数ｒが使用されていない場合（ステップＳ５８のＮＯ）、リソース捕捉関数のエラー処理の経路であるとして捕捉失敗候補経路数を１加算する（ステップＳ５９）。
【００７７】
ステップＳ５４〜Ｓ５９の処理で、関数ｆ，ｇと変数ｒの出現パタンの検査が終了すると、補足後使用区間調査フラグがｔｒｕｅである場合は、好適経路数を１加算する（ステップＳ６１）。なお、実行経路ｐがリソース捕捉関数のエラー処理の経路であるときもパタンに当てはまるので好適経路数は１加算される。つまり、実行経路ｐがリソース捕捉関数のエラー処理の経路であるときは捕捉失敗候補経路数と好適経路数がそれぞれ１加算される。
【００７８】
全ての実行経路ｐ∈ＰについてステップＳ５３〜Ｓ６１を処理すると（ステップＳ６２）、全ての実行経路ｐ∈Ｐにおいて関数ｆ，ｇと変数ｒが図９のパタンに当てはまるときは、関数ｆ，ｇと変数ｒがリソース捕捉関数、リソース解放関数、およびリソース格納変数である可能性はポジティブであると判定する（ステップＳ６３）。具体的には、抽出部１３は、実行経路集合Ｐが含む実行経路数｜Ｐ｜が好適経路数と一致し、好適経路数＞捕捉失敗好適経路数であれば、ポジティブと判定する。
【００７９】
以上の図１０，１１の処理により、リソース捕捉関数とリソース解放関数である可能性が高い関数ペアを抽出することができる。例えば、図４のソースコードからは、関数ペア集合＝｛（ｍｅｍｐｏｏｌ＿ａｌｌｏｃ，ｍｅｍｐｏｏｌ＿ｆｒｅｅ），（ｍｅｍｐｏｏｌ＿ａｌｌｏｃ，ｆｉｎｉｓｈ）｝が得られる。このうち関数ペア（ｍｅｍｐｏｏｌ＿ａｌｌｏｃ，ｆｉｎｉｓｈ）は、本来抽出したい関数ペアではないが、ｆｉｎｉｓｈの中でｍｅｍｐｏｏｌ＿ｆｒｅｅが呼び出されており、上記で説明したアルゴリズムに適合して抽出されるペアである（ｆａｌｓｅ  ｐｏｓｉｔｉｖｅ）。検出部１４が誤り検出処理を行う前に、抽出された関数ペアを人が精査してｆａｌｓｅ  ｐｏｓｉｔｉｖｅの関数ペアを取り除いてもよい。
【００８０】
また、図４のソースコード中のｍｅｍｐｏｏｌ＿ｃｏｎｓｔｒｕｃｔｏｒ関数とｍｅｍｐｏｏｌ＿ｄｅｓｔｒｕｃｔｏｒ関数もリソース捕捉関数とリソース解放関数であるが、本アルゴリズムに適合しなかったために抽出されていない。これは、図４のソースコードにはｍｅｍｐｏｏｌ＿ｃｏｎｓｔｒｕｃｔｏｒ関数で捕捉したリソースが使われない実行経路が存在するので、図１１のステップＳ５６の判定に適合しないためである。ステップＳ５６の判定処理を省略すれば、ｍｅｍｐｏｏｌ＿ｃｏｎｓｔｒｕｃｔｏｒ関数とｍｅｍｐｏｏｌ＿ｄｅｓｔｒｕｃｔｏｒ関数が抽出されるが、ｆａｌｓｅ  ｐｏｓｉｔｉｖｅが多くなることが見込まれる。
【００８１】
以上説明したように、本実施の形態によれば、入力したソースコードに現れる異なる２つの関数ｆ，ｇの全ての組み合わせについて、関数ｆを呼び出している行番号ｋを全て挙げて、関数ｆを呼び出した行番号ｋ以降の実行経路の全てにおいて、関数ｆの返却値を格納する変数ｒと関数ｇが一般的なリソース格納変数と一般的なリソース解放関数の出現パタンに当てはまるときは、関数ｆ，ｇをリソース捕捉関数とリソース解放関数として抽出し、リソース捕捉関数が捕捉したリソースを未初期化で参照している箇所を検出することにより、静的コード解析により、ユーザの定義したリソース捕捉関数とリソース解放関数の使い方の誤りを検出することが可能となる。例えば、ミドルウェアや基盤機能として開発したリソース捕捉解放ＡＰＩの利用時の未初期化リソースを参照する誤りを検出することが可能となる。
【符号の説明】
【００８２】
１…ソースコード検査装置
１１…入力部
１２…解析部
１３…抽出部
１４…検出部
【図１】
0006301851.tif 000002
【図２】
0006301851.tif 000003
【図３】
0006301851.tif 000004
【図４】
0006301851.tif 000005
【図５】
0006301851.tif 000006
【図６】
0006301851.tif 000007
【図７】
0006301851.tif 000008
【図８Ａ】
0006301851.tif 000009
【図８Ｂ】
0006301851.tif 000010
【図８Ｃ】
0006301851.tif 000011
【図９】
0006301851.tif 000012
【図１０】
0006301851.tif 000013
【図１１】
0006301851.tif 000014