(57)【要約】【課題】検証仕様の記述量を省力化し、複雑な検証仕様の誤りを減らし、偽反例を可及的に低減する。【解決手段】本発明の一態様としてのプログラム検証仕様生成装置は、イベントの発生による複数の各状態間の遷移を表す第１有限状態マシンを記述した第１仕様を入力する第１の入力手段と、（１）オブジェクト型と、（２）第１有限状態マシンの識別子と、（３）検証対象プログラムにおいて前記オブジェクト型をもつオブジェクトを操作する関数と前記識別子をもつ第１有限状態マシンに含まれるイベントとの対応と、の組を記述した第２仕様を入力する第２の入力手段と、前記関数の呼び出しによる、前記オブジェクト型をもつオブジェクトの各状態間の遷移を表す第２有限状態マシンを記述した、前記検証対象プログラムを検証するための検証仕様を生成する検証仕様生成手段と、を備える。【選択図】図１
2008242737.tif 000002
【特許請求の範囲】
【請求項１】
イベントの発生による複数の各状態間の遷移を表す第１有限状態マシンを記述した第１仕様を入力する第１の入力手段と、
（１）オブジェクト型と、（２）第１有限状態マシンの識別子と、（３）検証対象プログラムにおいて前記オブジェクト型をもつオブジェクトを操作する関数と前記識別子をもつ第１有限状態マシンに含まれるイベントとの対応と、の組を記述した第２仕様を入力する第２の入力手段と、
前記関数の呼び出しによる、前記オブジェクト型をもつオブジェクトの各状態間の遷移を表す第２有限状態マシンを記述した、前記検証対象プログラムを検証するための検証仕様を生成する検証仕様生成手段と、
を備えたプログラム検証仕様生成装置。
【請求項２】
前記第１の入力手段は、複数の第１有限状態マシンが記述された前記第１仕様を入力し、
前記第２の入力手段は、複数の前記組が記述された前記第２仕様を入力し、
前記検証仕様生成手段は、各前記組に含まれる関数の呼び出しによる、各前記オブジェクトの状態の組み合わせ間の遷移を表す第３の有限状態マシンを記述した検証仕様を生成することを特徴とする請求項１に記載のプログラム検証仕様生成装置。
【請求項３】
前記第２の入力手段は、前記オブジェクトの状態とイベントの発生とに基づく制約を表す論理式がさらに記述された前記第２仕様を入力し、
前記検証仕様生成手段は、前記制約に反する関数呼び出しに対してあらかじめ指定された状態へ遷移することを表す第３の有限状態マシンを記述した検証仕様を生成する、
ことを特徴とする請求項２に記載のプログラム検証仕様生成装置。
【請求項４】
前記あらかじめ指定された状態はエラー状態であることを特徴とする請求項３に記載のプログラム検証仕様生成装置。
【請求項５】
前記オブジェクトと、前記オブジェクトを操作する関数とを含む検証対象プログラムを前記検証仕様に基づいて検証するプログラム検証部をさらに備えたことを特徴とする請求項１に記載のプログラム検証仕様生成装置。
【請求項６】
イベントの発生による複数の各状態間の遷移を表す第１有限状態マシンを記述した第１仕様を入力し、
（１）オブジェクト型と、（２）第１有限状態マシンの識別子と、（３）検証対象プログラムにおいて前記オブジェクト型をもつオブジェクトを操作する関数と前記識別子をもつ第１有限状態マシンに含まれるイベントとの対応と、の組を記述した第２仕様を入力し、
前記関数の呼び出しによる、前記オブジェクト型をもつオブジェクトの各状態間の遷移を表す第２有限状態マシンを記述した、前記検証対象プログラムを検証するための検証仕様を生成する、
プログラム検証仕様生成方法。
【請求項７】
複数の第１有限状態マシンが記述された前記第１仕様を入力し、
複数の前記組が記述された前記第２仕様を入力し、
各前記組に含まれる関数の呼び出しによる、各前記オブジェクトの状態の組み合わせ間の遷移を表す第３の有限状態マシンを記述した検証仕様を生成する、
ことを特徴とする請求項６に記載のプログラム検証仕様生成方法。
【請求項８】
前記オブジェクトの状態とイベントの発生とに基づく制約を表す論理式がさらに記述された前記第２仕様を入力し、
前記制約に反する関数呼び出しに対してあらかじめ指定された状態へ遷移することを表す第３の有限状態マシンを記述した検証仕様を生成する、
ことを特徴とする請求項７に記載のプログラム検証仕様生成方法。
【請求項９】
前記あらかじめ指定された状態はエラー状態であることを特徴とする請求項８に記載のプログラム検証仕様生成方法。
【請求項１０】
さらに、前記オブジェクトと、前記オブジェクトを操作する関数とを含む検証対象プログラムを前記検証仕様に基づいて検証することを特徴とする請求項６に記載のプログラム検証仕様生成方法。
【請求項１１】
イベントの発生による複数の各状態間の遷移を表す第１有限状態マシンを記述した第１仕様を入力する第１ステップと、
（１）オブジェクト型と、（２）第１有限状態マシンの識別子と、（３）検証対象プログラムにおいて前記オブジェクト型をもつオブジェクトを操作する関数と前記識別子をもつ第１有限状態マシンに含まれるイベントとの対応と、の組を記述した第２仕様を入力する第２ステップと、
前記関数の呼び出しによる、前記オブジェクト型をもつオブジェクトの各状態間の遷移を表す第２有限状態マシンを記述した、前記検証対象プログラムを検証するための検証仕様を生成する第３ステップと、
をコンピュータに実行させるためのプログラム。
【請求項１２】
前記第１ステップでは、複数の第１有限状態マシンが記述された前記第１仕様を入力し、
前記第２ステップでは、複数の前記組が記述された前記第２仕様を入力し、
前記第３ステップでは、各前記組に含まれる関数の呼び出しによる、各前記オブジェクトの状態の組み合わせ間の遷移を表す第３の有限状態マシンを記述した検証仕様を生成する、
ことを特徴とするプログラム。
【請求項１３】
前記第２ステップでは、前記オブジェクトの状態とイベントの発生とに基づく制約を表す論理式がさらに記述された前記第２仕様を入力し、
前記第３ステップでは、前記制約に反する関数呼び出しに対してあらかじめ指定された状態へ遷移することを表す第３の有限状態マシンを記述した検証仕様を生成する、
ことを特徴とする請求項１２に記載のプログラム。
【請求項１４】
前記あらかじめ指定された状態はエラー状態であることを特徴とする請求項８に記載のプログラム。
【請求項１５】
前記オブジェクトと、前記オブジェクトを操作する関数とを含む検証対象プログラムを前記検証仕様に基づいて検証する第４ステップをさらに前記コンピュータに実行させることを特徴とする請求項１１に記載のプログラム。
【発明の詳細な説明】
【技術分野】
【０００１】
本発明は、プログラムを検証するための検証仕様を生成するプログラム検証仕様生成装置、方法およびプログラムに関する。
【背景技術】
【０００２】
計算機プログラムの論理的な誤りを検出する検証技術の中に型状態検証と呼ばれる公知の技法が存在する（非特許文献1および非特許文献2）。型状態検証は、検証対象のプログラムコードと利用者の記述した検証仕様とを入力としプログラムを実行することなく検証を行うものである。
【０００３】
型状態検証のための検証仕様は、プログラムコードに現れるオブジェクト変数の状態変化を有限状態マシンへ抽象化した仕様である。型状態検証における検証アルゴリズムは以下のようなものである。すなわち、プログラムコードの制御フローグラフを探索しながら、利用者の指定したオブジェクト変数への操作に応じて有限状態マシンを遷移させて、不正状態への遷移有無を検査し、不正状態への遷移が存在する場合は遷移パスを反例として表示する。
【０００４】
型状態検証の長所は、プログラムコードを直接の検証対象とする点、プログラムの実行が不要な点、プログラムの全パスを調べる点にある。一方、型状態検証の短所は、プログラムコードの中の変数値や分岐先を未確定として取り扱うため、検証結果が不正確となり実際には実行し得ないパスに関するエラー報告（偽反例）が生ずる点にある。
【非特許文献１】Dawson Engler, Benjamin Chelf, Andy Chou, and Seth Hallem. "Checking System Rules Using SystemSpecific, Programmer-Written Compiler Extensions." In Proceedings of the Fourth Symposium on Operating Systems Design and Implementation, San Diego, CA, October 2000.
【非特許文献２】Manuvir Das, Sorin Lerner, and Mark Seigle. Esp: Pathsensitive program verification in polynomial time. In Proceedings of the ACM SIGPLAN 2002 Conference on Programming language design and implementation.
【非特許文献３】Gregor Kiczales, Erik Hilsdale, Jim Hugunin, Mik Kersten, Jeffrey Palm, and William G. Griswold. An overview of AspectJ. In Proceedings of the European Conference on Object-Oriented Programming, Budapest, Hungary, 18--22 June 2001.
【発明の開示】
【発明が解決しようとする課題】
【０００５】
型状態検証を行うにあたり、利用者は検証するオブジェクト変数の内部状態を抽象化した有限状態マシンを正確に記述する必要がある。大規模なプログラムコードに対して検証仕様を記述して型状態検証を行うと以下の様な状況が生ずる。
1. 複数の異なるオブジェクトが類似の状態遷移をする場合が多く、この場合に個別に検証仕様を記述すると重複する記述の量が多くなる。
2. 有限状態マシンの状態数が多いと検証仕様を誤り無く記述することが困難となる。
3. 型状態検証の報告した反例が現実に起き得るか否かの判断が困難である。
【０００６】
本発明は、検証仕様の記述量の省力化、複雑な検証仕様における誤りの低減、偽反例の可及的な低減の少なくともいずれかを達成できるプログラム検証仕様生成装置、方法およびプログラムを提供する。
【課題を解決するための手段】
【０００７】
本発明の一態様としてのプログラム検証仕様生成装置は、
イベントの発生による複数の各状態間の遷移を表す第１有限状態マシンを記述した第１仕様を入力する第１の入力手段と、
（１）オブジェクト型と、（２）第１有限状態マシンの識別子と、（３）検証対象プログラムにおいて前記オブジェクト型をもつオブジェクトを操作する関数と前記識別子をもつ第１有限状態マシンに含まれるイベントとの対応と、の組を記述した第２仕様を入力する第２の入力手段と、
前記関数の呼び出しによる、前記オブジェクト型をもつオブジェクトの各状態間の遷移を表す第２有限状態マシンを記述した、前記検証対象プログラムを検証するための検証仕様を生成する検証仕様生成手段と、
を備える。
【０００８】
本発明の一態様としてのプログラム検証仕様生成方法は、
イベントの発生による複数の各状態間の遷移を表す第１有限状態マシンを記述した第１仕様を入力し、
（１）オブジェクト型と、（２）第１有限状態マシンの識別子と、（３）検証対象プログラムにおいて前記オブジェクト型をもつオブジェクトを操作する関数と前記識別子をもつ第１有限状態マシンに含まれるイベントとの対応と、の組を記述した第２仕様を入力し、
前記関数の呼び出しによる、前記オブジェクト型をもつオブジェクトの各状態間の遷移を表す第２有限状態マシンを記述した、前記検証対象プログラムを検証するための検証仕様を生成する。
【０００９】
本発明の一態様としてのプログラムは、
イベントの発生による複数の各状態間の遷移を表す第１有限状態マシンを記述した第１仕様を入力する第１ステップと、
（１）オブジェクト型と、（２）第１有限状態マシンの識別子と、（３）検証対象プログラムにおいて前記オブジェクト型をもつオブジェクトを操作する関数と前記識別子をもつ第１有限状態マシンに含まれるイベントとの対応と、の組を記述した第２仕様を入力する第２ステップと、
前記関数の呼び出しによる、前記オブジェクト型をもつオブジェクトの各状態間の遷移を表す第２有限状態マシンを記述した、前記検証対象プログラムを検証するための検証仕様を生成する第３ステップと、
をコンピュータに実行させる。
【発明の効果】
【００１０】
本発明により、検証仕様の記述量の省力化、複雑な検証仕様における誤りの低減、偽反例の可及的な低減の少なくともいずれかを達成できる。
【発明を実施するための最良の形態】
【００１１】
最初に従来の型状態検証について簡単に例示した後、本提案について説明する。
【００１２】
図１２は、従来の型状態検証（非特許文献１）を説明する図である。
【００１３】
検証仕様１０１と検証対象プログラム１０２とをプログラム検証装置１０３に入力する。プログラム検証装置１０３では型状態検証アルゴリズムに従って検証を行って検証結果１０４を出力する。検証仕様１０１は専用言語Xで記述され、プログラム検証装置１０３は専用言語Xで記述された検証仕様のみ解釈可能である。
【００１４】
検証対象プログラムの一例を例１に示す。例１は、ファイル変数f、排他変数mと整数xを状態変数として、各変数の開始操作を実行した後、ファイルの読み書きを繰り返して、各変数の終了操作を実行した後、プログラムを終了するものである。「＊」「...」には適当な式または文字列が入る。
----- 例１：検証対象 -----
file f;        // ファイル
mutex m;                // 排他変数
int x;
f.fopen("test.txt");
m.init();
while (*) {
m.lock();
if (*) {
x = f.read(..);
} 
else {
x = f.write(..);
if (x < 0) break;
}
m.unlock();
}
f.fclose();
m.destroy();
-----
【００１５】
検証仕様の一例（検証仕様１）を例２に示す。検証仕様１は、排他変数の利用方法を規定する有限状態マシンを定義し、有限状態マシンの構造は図１６に示されるものとなる。この仕様（名称：mutex_check1）は、プログラム変数の型"{mutex}"の抽象状態を記号"v"で参照する。状態変数"v"は初期状態を"start"として、プログラムの変数出現で"start"から未定義状態"v.undef"へ遷移する。開始操作"v.init()"を呼ぶと初期化済み状態v.validへと遷移する。以下、同様に状態v.undef,v.validの間の遷移を記述しており、遷移先が{err(..)}のとき不正と規定する。つまり、この検証仕様１は開始操作前の排他変数の制御を禁止している。検証仕様１の記述に含まれる縦線「|」は“あるいは（ＯＲ）”を表す。例えば、未定義状態"v.undef"のときv.init()を呼ぶと初期化済み状態v.validに遷移し、v.call(args)を呼ぶと不正となる。
----- 例２：検証仕様１ -----
sm mutex_check1 {
state decl { mutex } v;
decl any_fn_call call;
decl any_args args;
start:
{ v } ==> v.undef;
v.undef:
{ v.init() } ==> v.valid
| { v.call(args) } ==> { err("1") };
v.valid:
{ v.lock() } ==> v.valid
| { v.unlock() } ==> v.valid
| { v.destroy() } ==> v.undef
| { v.call(args) } ==> { err("2") };
}
-----
【００１６】
図１２のプログラム検証装置Ｘでは、公知の手順により、例１に示した検証対象プログラムを図１３に示す制御フローグラフへ変換する。制御フローグラフにおける各基本ブロックは、プログラムの分岐や合流を含まない最大のコード片となる。基本ブロックの間は、分岐先を示す有向辺で結ぶ。プログラム検証装置Xは、制御フローグラフを実行可能な順に探索して、排他変数mが出現する度に、検証仕様１に定義した有限状態マシンを遷移させる。各基本ブロックの入口と出口に到達可能な状態を記録した例を図１４に示す。「Ｕ」は未定義状態"undef"を略記し、「Ｖ」は初期化済み状"v.valid"を略記したものである。この例では不正な遷移は検出されない。
【００１７】
より詳しい検証仕様として、排他変数のロック状態を考慮した検証仕様２を例３に示す。この検証仕様２は、図１７に示す構造の有限状態マシンを定義している。この例３において、上記と同様にして制御フローグラフを生成し各基本ブロックの入口と出口に到達可能な状態を記録した例を図１５に示す。「Ｌ」はロック状態"v.locked"を略記したものである。図１５の例ではロック状態"v.locked"で終了処理"v.destroy()"するパスが存在し、不正有りと判定される。
----- 例３：検証仕様２ -----
sm mutex_check2 {
state decl { mutex } v;
decl any_fn_call call;
decl any_args args;
start:
{ v } ==> v.undef;
v.undef:
{ v.init() } ==> v.valid
| { v.call(args) } ==> { err(“error1") };
v.valid:
{ v.lock() } ==> v.locked
| { v.destroy() } ==> v.undef
| { v.call(args) } ==> { err(“error2") };
v.locked:
{ v.unlock() } ==> v.valid
| { v.call(args) } ==> { err(“error3") };
}
-----
【００１８】
ファイルに対しても同様の開始操作前のアクセスを検査したい場合は、例２の検証仕様１において"{mutex}"を"{file}"へ、"v.init()"を"v.open()"へ等と置換することで検証仕様を生成できる。
【００１９】
このように、従来の検証仕様１、２では、有限状態マシンの定義と、プログラムとの対応関係（変数との対応関係、関数との対応関係）の定義とを同じ仕様記述の中で同時に記述している。
【００２０】
本実施の形態では、検証仕様を抽象仕様と具象仕様とに分けて記述する。これにより抽象仕様の共有化が可能となる。より詳しくは、図４に示すように、抽象仕様では、複数の各状態と、複数の各イベントと、イベントの発生による状態間の遷移とにより有限状態マシンを定義する。また、具象仕様では、抽象仕様により定義される有限状態マシンと検証対象プログラムにおけるプログラム変数（オブジェクト）の型（タイプ）との対応関係を記述し、また該有限状態マシンのイベントと検証対象プログラムにおける関数との対応関係を記述する。具象仕様に記述されている表明式は本実施の形態の特徴の１つであり、これについては後述する。表明式は記述されないこともある。このような抽象仕様と具象仕様とを合成することにより検証仕様を生成する。以下、本実施の形態について詳細に説明する。
【００２１】
本実施の形態に係わる抽象仕様の例（抽象仕様１、２）を例４、例５に示す。また具象仕様の例（具象仕様１、２）を例６、例７に示す。抽象仕様は第１仕様に相当し、具象仕様は第２仕様に相当する。
【００２２】
例４に示した抽象仕様１の解釈は以下のようになる。名称"object"（第１有限状態マシンの識別子）をもつ有限状態マシンは、状態"undef","valid"と、遷移イベント（あるいは単にイベント）"ini","fin","use"と、遷移イベントの発生による状態の遷移とを定義している。例えば、状態"undef"のとき遷移イベントiniが起こると、状態”valid”に遷移する。明示的に定義されない遷移は全てエラー状態へ遷移すると約束する。つまり、抽象仕様（第１仕様）は、イベントの発生による複数の各状態間の遷移を表す第１有限状態マシンを記述している。
【００２３】
例６に示した具象仕様１の解釈は、有限状態マシン（抽象仕様）"object"をプログラム変数の型（オブジェクト型）"file"に対応させ、遷移イベント"ini"を、プログラム関数（型"file"をもつオブジェクトを操作する関数）"open"に対応させる等となる。具象仕様１の名称は"file"である。具象仕様１の下部に記述されている「ｆ」、具象仕様２の下部に記述されている「ｍ」は、これらの具象仕様に対して付けたラベルであり、上記オブジェクト型をもつオブジェクトを仮想的に表している。f.iniとした場合、これは上記オブジェクト型"file"をもつオブジェクトに対するイベントiniを指すものとする。
【００２４】
本実施の形態では、このような抽象仕様１と具象仕様１とを、また、抽象仕様２と具象仕様２とを、後述するプログラム検証仕様合成装置（仕様合成部）で合成することにより検証仕様を生成する。
----- 例４：抽象仕様１ -----
// 汎用オブジェクト
fsm object {
state: undef, valid;
event: ini, fin, use;
delta: 
(undef, ini -> valid),
(valid, fin -> undef),
(valid, use -> valid);
}
-----
----- 例５：抽象仕様２ -----
// 排他制御変数
fsm mutex { 
state: undef, valid, locked;
event: ini, fin, lock, unlock;
delta: 
(undef, ini -> valid),
(valid, fin -> undef),
(valid, lock -> locked),
(locked, unlock -> valid);
}
-----
----- 例６：具象仕様 １-----
// ファイル操作
spec file {
fsm(object): type(file) {
ini: call(open(..));
fin: call(close(..));
use: call(read(..)) || call(write(..));
} f;
}
-----
----- 例７：具象仕様 ２-----
// ロック操作
spec lock1 {
fsm(object): type(mutex) {
ini: call(init(..));
fin: call(destroy(..));
use: call(lock(..)) || call(unlock(..)); 
} m;
}
-----
【００２５】
次に、より複雑な検証仕様の例として、プログラムの排他変数とファイルとの組み合わせに関する検証を考える。
【００２６】
例えば、ファイル操作中は排他変数がロック状態であることを検証により確認したいとする。これに対応する有限状態マシンの例を図５に示す。なお、状態ラベルはU=Undef、V=Valid、L=Lockedと略記した。有限状態マシンの状態はファイルと排他変数の組み合わせとなり、ファイルの状態が2個（ＵとＶ）、排他変数の状態が3個（ＵとＶとＬ）とすると、状態数はエラー状態を含めて、(2*3+1)=7個となる。不正となる遷移はたとえば破線に示される遷移であり、この遷移を含む不正となる遷移をすべてエラー状態への遷移（図中右上の「other」参照）としている。この様な検証仕様（有限状態マシン）は、構成のルールは単純だが、従来の検証仕様の様に全ての状態と遷移とを列挙して定義するのは容易でない。解決策として、各型（file, mutex等）に組み合わせるべき抽象仕様と、以下に説明する“表明式（表明の論理式）”とを記述した具象仕様を作成する。
【００２７】
以下の例８に示す具象仕様３はロック付ファイル操作に関する具象仕様であり、抽象仕様"object"と"mutex"を、プログラム変数の型"file"と"mutex"へそれぞれ対応させるとともに、各型に属するプログラム変数の遷移イベントを定義している。
【００２８】
より詳細には、具象仕様３には、
（１）オブジェクト型(file)と、（２）第１有限状態マシンの識別子(object)と、（３）検証対象プログラムにおいて前記オブジェクト型をもつオブジェクトを操作する関数(open(..),close(..)など)と前記識別子(object)をもつ第１有限状態マシンに含まれるイベント（ini,finなど）との対応と、の組と、
（１）オブジェクト型(mutex)と、（２）第１有限状態マシンの識別子(mutex)と、（３）検証対象プログラムにおいて前記オブジェクト型をもつオブジェクトを操作する関数(init(..),destroy(..)など)と前記識別子(mutex)をもつ第１有限状態マシンに含まれるイベント（ini,finなど）との対応と、の組と、
の２つの組が記述されている。
【００２９】
具象仕様３に基づく有限状態マシンのとる各状態は、基本的に、参照する各抽象仕様の状態の組み合わせとなる。ただし、利用者が文"assert"を用いて記述した“表明式”を偽とする状態または遷移をエラー状態またはエラー状態への遷移とする。
【００３０】
すなわち、文"assert"を用いて記述した表明式が偽となる、状態と遷移イベントとの組の遷移先はエラー状態と約束する。例えば、例８の表明式"!f.use || (f.use && m@locked)"の意味は、「変数"f"（オブジェクト）のイベント"use"が発生する時は、変数"m"（オブジェクト）の状態が"locked"とする」となる。つまり、変数"f"のイベント"use"が発生しないとき、または、変数"m"の状態が"locked"のときに変数"f"のイベント"use"が発生するとき、文"assert"は、true(真)（エラーでない）となる。表明式は、オブジェクトの状態とイベントの発生とに基づく制約を表す論理式に相当する。なお、表明式の真偽値を決定するアルゴリズムの詳細は後述する。
【００３１】
本実施の形態では、このような具象仕様３と、具象仕様３で用いられている各抽象仕様（"object", "mutex"）とを、後述するプログラム検証仕様合成装置（仕様合成部）で合成することにより検証仕様を生成する。
----- 例８：具象仕様３ -----
// ロック付ファイル操作
spec locked_file {
fsm(object): type(file) {
ini: call(open(..));
fin: call(close(..));
use: call(read(..)) || call(write(..));
} f;
fsm(mutex): type(mutex) {
ini: call(init(..));
fin: call(destroy(..));
lock: call(lock(..));
unlock: call(unlock(..));
} m;
assert(!f.use || (f.use && m@locked));    ←表明式
}
-----
【００３２】
図１は、本実施の形態としてのプログラム検証仕様生成装置（仕様合成部１１）を備えたプログラム検証装置の構成を示すブロック図である。図２は、本プログラム検証装置の動作を概略的に示すフローチャートである。図２のフローチャートに示される各ステップを実行する命令コードを記述したプログラムをコンピュータに実行させることによって図１のプログラム検証装置の動作が実現されてもよい。またこの命令コードを記述したプログラムがコンピュータ読み取り可能な記憶媒体に記憶され、コンピュータによって読み出されて実行されてもよい。
【００３３】
利用者から入力手段を用いてこのプログラム検証装置に対して抽象仕様２１（第１仕様）と具象仕様２２（第２仕様）とが入力される（ステップＳ１１、Ｓ１２）。仕様合成部（プログラム検証仕様生成装置）１１は、入力された抽象仕様２１（第１仕様）と具象仕様２２（第２仕様）とから中間検証仕様２３を生成する（ステップＳ１３）。検証仕様変換部１２は、生成された中間検証仕様２３を、複数の検証方式のうち所望の検証方式に対応した入力検証仕様２４（第２または第３の有限状態マシンを記述した検証仕様）に変換する（ステップＳ１４）。プログラム検証部１３は、検証仕様（入力検証仕様）２４に基づいて検証対象プログラム２５を検証し（ステップＳ１５）、プログラムの検証結果２６を出力する（ステップＳ１６）。中間検証仕様２３を所望の検証方式に対応した検証仕様に変換することで、複数の検証方式に対応可能としている。本例では専用言語Ｘで記述された検証仕様に変換している。このように、本実施の形態では、いったん中間検証仕様を生成し、生成した中間検証仕様を所望の検証方式に対応した検証仕様に変換することで複数の検証仕様に対応可能としているが、抽象仕様と具象仕様とから直接に検証仕様（第２または第３の有限状態マシンを記述した検証仕様）を生成する構成も当然に可能である。
【００３４】
図３は、仕様合成部１１の構成を詳細に示すブロック図である。
【００３５】
仕様合成部１１の入力側には、表抽出部３１、３３が設けられている。ここでは表抽出部３１、３３は仕様合成部１１の外側に設けられているが、仕様合成部１１の内部に設けてもよい。
【００３６】
表抽出部３１は、各抽象仕様２１からそれぞれ遷移表（個別）３２を抽出する。例４に示した名称"object"の抽象仕様１から抽出した遷移表の例を図６に、例５に示した名称"mutex"の抽象仕様２から抽出した遷移表の例を図７に示す。遷移表（個別）３２は、状態とイベントとの組から遷移先の状態を表すものである。例えば図６において、"Undef"のときイベント"ini"が発生するとValidに状態が遷移する。抽象仕様と、該抽象仕様から抽出された遷移表とは等価であり、コンピュータ上では抽象仕様は遷移表の形で管理される。ここでは抽象仕様２１から遷移表（個別）を抽出し、抽出した遷移表（個別）を仕様合成部１１に入力しているが、あらかじめ遷移表（個別）を作成しておき、この遷移表（個別）を仕様合成部１１に直接入力してもよい。この場合、表抽出部３１を省略できる。
【００３７】
表抽出部３３は、具象仕様２２から、対応表３４と、表明式３５とを抽出する。例８に示した具象仕様３から抽出した対応表の例を、図１１に示す。また具象仕様３から抽出される表明式３５は、"!f.use || (f.use && m@locked) "である。対応表は各オブジェクト型を抽象仕様に対応づけ、また、抽象仕様におけるイベントを該抽象仕様に対応するオブジェクト型をもつオブジェクトを操作する関数に対応づけている。具象仕様３から表明式を除いた部分と、図１１の対応表とは等価であり、コンピュータ上では当該表明式を除いた部分は、このような対応表の形で管理される。ここでは具象仕様２２から対応表３４および表明式３５を抽出して仕様合成部１１に入力しているが、あらかじめ対応表と表明式との組を用意しておき、これらを仕様合成部１１に直接入力してもよい。この場合、表抽出部３３を省略できる。
【００３８】
状態積生成部３６は、各抽象仕様２１から抽出された遷移表（個別）３２を、対応表３４に基づいて合成して遷移表（合成）３７を得る。図６および図７の遷移表を、図１１の対応表に基づいて合成して得られた遷移表（合成）３７が図９に示される。遷移表３７は、各遷移表（個別）３２における状態の組み合わせ（いずれか一方がエラーである組み合わせは全てエラー状態（Error）として扱う）において、具象仕様２２における各型（file, mutexなど）のイベントが発生したときの遷移先を示したものである。例えば、状態（U,U）において、file型のオブジェクトに関するイベントini（f.ini）が発生したときは、状態（V,U）に遷移する。
【００３９】
表明式評価部３８は、表明式３５と、遷移表（合成）３７の表形式（横項目と縦項目との交差部の値は使用しない）とから表明表３９を生成する。図９の遷移表（合成）３７の表形式と、表明式"!f.use || (f.use && m@locked) "とから生成された表明表３９を図８に示す。表明表３９は以下のようにして生成する。図９の遷移表（合成）３７の形式において、横項目（状態）と、縦項目（イベント）との組みが、表明式３５を満たす場合は、該組みに対応するマスにTRUE（真）を入力し、表明式３５を満たさない場合は、該組みに対応するマスにFALSE（偽）を入力する。たとえば、(U,U)と、f.iniとの組みは、表明式３５中の"!f.use"に該当するので、上記表明式を満たし、よって"TRUE"を該当するマス（左上のマス）に入力する。また、(U,U)と、f.useとの組みは、"!f.use "および"(f.use && m@locked) "のいずれも満たさないため、"FALSE"を該当するマス（左上から下に３つ目のマス）に入力する。また、(V,L)と、f.useとの組みは、"(f.use && m@locked) "を満たすため、"TRUE"を該当するマスに入力する。表明表３９の詳細な生成アルゴリズムについては後述する。
【００４０】
遷移表修正部４０は、遷移表（合成）３７を表明表３９に基づいて修正することにより遷移表（最終）４１を生成する。図９の遷移表（合成）３７を、図８の表明表３９に基づいて修正した遷移表（最終）の例を図１０に示す。遷移表（最終）は以下のようにして生成する。図８において"TRUE"となっているマスについては、当該マスに対応する図９の値をそのまま使用し、図８において"FALSE"となっているマスについては、常に"Error"とする。図１０の表において"Error*"は、このエラーが表明式３５に基づくものであることを示す。すなわち、もし表明式３５がなければ、当該"Error*"が入っていたマスには、図９の値（Errorでない）がそのまま用いられることになる。
【００４１】
遷移表修正部４０によって生成された遷移表（最終）４１と、表抽出部３３によって抽出された対応表３４とが、仕様合成部１１の出力となる。すなわち、遷移表（最終）４１と対応表３４との組は、図１の中間検証仕様２３に相当する。
【００４２】
以上の説明では、具象仕様２２に表明式が記述されている場合を示したが、具象仕様２２に表明式が記述されていない場合は、遷移表（合成）３７を修正する必要はないため、遷移表（合成）３７と対応表３４との組を中間検証仕様２３として出力すればよい。例えば、例４の抽象仕様１と例６の具象仕様１とを仕様合成部１１へ入力する場合、または、例５の抽象仕様２と例７の具象仕様２とを仕様合成部１１へ入力する場合がこれに相当する。
【００４３】
以下、仕様合成部１１における仕様合成の詳細なアルゴリズムを手順１〜手順４として記す。状態積生成部３６が手順１の(1)-(3)と手順２に対応し、表明式評価部３８が手順４に対応し、遷移表修正部４０が手順１の(4)-(6)と手順３に対応する。
【００４４】
以下の説明において、検証仕様の有限状態マシンはＭ=(Ｑ',Σ,δ,q0,Ｑ)で定義され各記号の意味は以下の定義１に従うとする。
----- 定義１：有限状態マシン -----
Ｑ ：state文の状態集合（エラー状態以外の全ての状態（受理状態）の集合）
Ｑ'： 全状態 = Ｑ∪{error}
error ： エラー状態
Σ ： event文の記号集合
δ ： 状態マシンの遷移関数
Ｑ' * Σ → Ｑ'
delta文に明記されない遷移はerror遷移と見なす。
error状態からの遷移先は全てerror状態とする。
q0 ： 初期状態（state文の最初に宣言される状態）
【００４５】
入力となる具象仕様と抽象仕様とから関連する遷移表（個別）M[i]と表明式exprを読み込み、遷移表（最終）Mを出力する。手順１で用いる遷移関数の計算手順は手順２および手順３に記載される。
----- 手順１：仕様合成 -----
機能：仕様合成
入力：有限状態マシンＭ[1]、,,,Ｍ[n]、表明expr
出力：有限状態マシンＭ
事例：図１０の表
(1) 有限状態マシンM[i]の状態集合Ｑ[i]（エラー状態は含まない）の直積を生成し、エラー状態を加えて、状態集合Ｑ'を得る。
すなわち、有限状態マシンMの状態集合はＱ'=Ｑ∪{error}とする。
Ｑ := (Ｑ[1] * Ｑ[2] * ... * Ｑ[n])
= { (q1,q2,...,qn) | q1 in Ｑ[1] ∧ ... ∧ qn in Ｑ[n] }
(2) 有限状態マシンM[i]のイベント集合Σ[i]の和を生成し、Mのイベント集合Σとする。
Σ := Σ[1] ∪ Σ[2] ∪ ... ∪ Σ[n]
= { a | a in Σ[1] ∨ ... ∨ a in Σ[n] }
(3) 表明exprを考慮しない遷移関数trans(q,a)を手順2の通り定義し、遷移表を計算する。
(4) 表明exprの真偽値表valid(q,a)を生成する。
(5) 表明expr(q,a)の真偽値表の値valid(q,a)が真とき遷移先trans(q,a)を用い、偽のとき遷移先errorとする。
(6) この遷移表delta(q,a)を有限状態マシンMの遷移関数δとする。
-----
【００４６】
以下に示す手順２は、表明式を考慮しない場合の、積状態を持つ有限状態マシンの遷移先を定める。状態組qおよび遷移イベントaを入力とし、状態組の遷移先qを決める。遷移イベントaと対応する状態要素の場所iを決め、場所iの状態のみ遷移させた状態組をqとする。
----- 手順２：表明式を考慮しない遷移関数 -----
機能：表明式を考慮しない有限状態マシンの遷移delta(q,a)を計算する
入力：q:Ｑ'、a:Σ、delta[i]:Ｑ'[i] * Σ[i] → Ｑ'[i]
出力：p:Ｑ'
事例：図９の表
trans(q:Ｑ', a:Σ):Ｑ' :=
let q = (q[1],q[2],...,q[n])
var p = (p[1],p[2],...,p[2])
for each i in [1,2,...,n] do
if a in Σ[i] then
p[i] := delta[i](q[i],a)
else
p[i] := q[i]
endif
if p[i] = error then
return error
endif
endfor
return p
-----
【００４７】
以下に示す手順３の中で利用する表明式は、手順３の下に記述した定義２で定義され、その評価手順は手順４を用いる。手順３は、表明式を考慮していない遷移表（合成）と、表明表とを参照して、各状態qと遷移イベントaに対して、表明式を考慮した遷移先を決定する。具体的には、表明表の値が真の場合に遷移表（合成）の遷移先を採用して、表明表の値が偽の場合に遷移先をエラー状態とする。
----- 手順３：表明式を考慮した遷移関数 -----
機能：表明式を考慮した有限状態マシンの遷移表を計算する。
入力：表明式を考慮していない遷移表trans(q,a)、表明表valid(q,a)
出力：表明式を考慮した遷移表delta:Ｑ' * Σ → Ｑ'
事例：図１０の表
delta(q:Ｑ, a:Σ):Ｑ :=
if valid(q,a) then
return trans(q,a)
else
return error
endif
-----
---- 定義２：表明式（表明の論理式） -----
以下のBNF記法で定義される論理式とし、記号"&&"は論理積、記号"||"が論理和、記号"!"が論理否定を意味し、状態変数"v@state"やイベント記号"v.event"は状態とイベントに応じて真偽値を取る。
expr ::= v@state | v.event | expr && expr | expr || expr | !expr
例）expr = (x@valid && y.use) && !(x@valid && z@locked)
【００４８】
以下に示す手順４が表明表の計算手順であり、状態qとイベントaを入力した場合に、表明式の真偽値を定める。具体的には、論理式の状態項"v@state"やイベント項"v.event"に真偽値を割り当てた後、ブール式の評価手順にしたがい表明式の真偽値を決定する。手順４は、再帰的呼び出し方式の手順の定義であり、現在の入力式eが論理積形ならばand(..)を呼び、論理和形ならばor(..)を呼び、論理否定形ならばnot(..)を呼び、状態項やイベント項ならば真偽値を割り当てる。再帰呼び出しの回数が増加すると、論理演算子の数が減少するため、この手順は必ず停止して表明式の値を定める。なお、関数and(..)やor(..)not(..)は、通常のブール値に対する関数とする。
----- 手順４：表明式の評価 -----
機能：状態qとイベントaに対する表明式の真偽値を計算する。
入力：表明式e、状態q、イベントa
出力：真偽値（trueまたはfalse）
事例：図８の表
valid(e:Exp, q:Ｑ, a:Σ):bool :=
match e with 
e1 && e2 => and(valid(e1,q,a), valid(e2,q,a))
e1 || e2 => or(valid(e1,q,a), valid(e2,q,a))
! e1 => not(valid(e1,q,a))
v@state => if q[v] = state then true else false 
v.event => if a = v.event then true else false
endcase
-----
【００４９】
図１の検証仕様変換部１２において行われる検証仕様変換の計算手順（アルゴリズム）を以下に例示する。
【００５０】
有限状態マシンの中間検証仕様２３を、検証対象となるプログラムの実行時に検証を行うためのプログラムコード（入力検証仕様）へ変換する方法を示す。ただし、他の検証方式に対しても、検証仕様の記述が有限状態マシンの形式である限りは、同様の方法で中間仕様から入力検証仕様を生成することができる。例えば、プログラムを実行することなく検証を行う型状態検証のための入力検証仕様を中間検証仕様２３から変換することも当然に可能である。このように複数の異なる検証方式に対応した検証仕様をそれぞれ生成し、各検証仕様によるプログラム検証を行うことで偽反例の除去効果を得ることができる。
【００５１】
以下の手順５は、アスペクト指向言語AspectJの形式で検証仕様に定義した有限状態マシンを生成する例であり、ここで出力したアスペクトは検証対象のプログラムと共にコンパイルすることで、プログラム実行時に状態マシンを遷移させて検証を行うことができる。型状態検証で反例が出た場合に、実際に対応するパスが生ずるか実際に実行して調べる場合に有効である。
----- 手順５：入力検証仕様生成 -----
入力：中間仕様Ｍ=(Ｑ',Σ,δ,q0,Ｑ)
出力：有限状態マシンを実装するアスペクトモジュール
(1) 適当な検証仕様名Idのアスペクトaspectを修飾子pertarget(obj())で生成する
aspect Id pertarget(target(Type)) { ... }
(2) アスペクトのメンバに、状態Qを保持する変数qを宣言し、初期状態q0に初期化する
aspect ... { int q; ... }
(3) アスペクトのメンバに配列delta[][]を宣言し遷移δを格納する
aspect ... { ...; int delta[N][M]; ... }
(4) アスペクトのメンバに対象型Typeに対応するpointcut文を宣言する
aspect ... { ...; pointcut obj(): target(Type); ... }
(4) アスペクトのメンバにイベントΣに対応するpointcut文を宣言する
aspect ... { ...; pointcut evt(): call(...); ... }
(5) アスペクトのpointcut文に対応するアドバイスを宣言し、状態遷移を記述する
aspect ... { ...; before() : evt() { ... } ... }
a in Σに対応するアドバイス
before() : evt() { q = delta[q][a]; if (q == error) err(); }
-----
【００５２】
なお、以下のアスペクトの例９は非特許文献３のAspectJ言語の記法に従う。この例のアスペクトの解釈は、アスペクト指向言語の処理系が、型Typeごとに名称Idのアスペクトを生成pertarget(obj())して、型Typeのオブジェクトへのアクセスが発生するとアドバイスbefore():evt(){...}を呼び出す。
----- 例９：入力検証仕様（AspectJ言語の形式） -----
aspect Id pertarget(obj()) {
int q = q0;
int delta[][] = { ... };
pointcut obj() : target(Type);
pointcut evt1() : call(..);   // イベントa1
...
before() : ev1() { q = delta[q][a1]; if (q == error) err(); }
...
}
-----
【００５３】
以上のように、本実施の形態によれば、検証仕様を抽象仕様と具象仕様に分けて利用者が記述し、両者を合成して検証仕様（あるいは中間検証仕様）を生成するようにしたことにより、検証仕様の記述量を省力化する効果を得ることができる。またこれにより、抽象仕様の繰り返しの再利用が可能となる。
【００５４】
また、本実施の形態によれば、検証仕様を抽象仕様と具象仕様に分けて利用者が記述し、両者を合成して検証仕様（あるいは中間検証仕様）を生成するようにしたことにより、複雑な検証仕様の誤りを減らす効果を得ることができる。
【００５５】
また、本実施の形態によれば、検証仕様を抽象仕様と具象仕様に分けて利用者が記述し、両者を合成して検証仕様（あるいは中間検証仕様）を生成するようにしたことにより、抽象仕様の繰り返しの再利用が可能となる。
【００５６】
また、本実施の形態によれば、検証仕様を抽象仕様と具象仕様に分けて利用者が記述し、両者から中間検証仕様を生成し、生成した中間検証仕様を個別の検証方式に対応した検証仕様（入力検証仕様）へ変換するようにしたことにより、複数の異なる検証方式を組み合わせてプログラム検証を行うことで、偽反例の除去効果を得ることができる。
【図面の簡単な説明】
【００５７】
【図１】本発明の一実施形態としてのプログラム検証仕様合成装置を備えたプログラム検証装置の概略構成を示すブロック図。
【図２】図１のプログラム検証装置の動作を概略的に示すフローチャート。
【図３】プログラム検証仕様合成装置（仕様合成部）の詳細構成を示すブロック図。
【図４】抽象仕様と具象仕様間の関係を示す図。
【図５】抽象仕様（ファイル,排他変数）を説明する図。
【図６】抽象仕様の遷移表（fsm object）を示す図。
【図７】抽象仕様の遷移表（fsm mutex）を示す図。
【図８】表明式の真偽値表を示す図。
【図９】有限状態マシンの遷移表（表明式の考慮なし）を示す図。
【図１０】有限状態マシンの遷移表（表明式の考慮あり）を示す図。
【図１１】具象仕様の対応表を示す図。
【図１２】従来のプログラム検証を説明する図。
【図１３】制御フローグラフの例を示す図。
【図１４】型状態検証の動作例（mutex_check1）を説明する図。
【図１５】型状態検証の動作例（mutex_check2）を説明する図。
【図１６】従来の検証仕様１に対応した有限状態マシン（検証仕様）を示す図。
【図１７】従来の検証仕様２に対応した有限状態マシン（検証仕様）を示す図。
【図１】
2008242737.tif 000003
【図２】
2008242737.tif 000004
【図３】
2008242737.tif 000005
【図４】
2008242737.tif 000006
【図５】
2008242737.tif 000007
【図６】
2008242737.tif 000008
【図７】
2008242737.tif 000009
【図８】
2008242737.tif 000010
【図９】
2008242737.tif 000011
【図１０】
2008242737.tif 000012
【図１１】
2008242737.tif 000013
【図１２】
2008242737.tif 000014
【図１３】
2008242737.tif 000015
【図１４】
2008242737.tif 000016
【図１５】
2008242737.tif 000017
【図１６】
2008242737.tif 000018
【図１７】
2008242737.tif 000019