モデル検査の応用 徳田研究室 西村太一 目次 • モデル検査とSPINついて • 仕様の検証例 • Cプログラムの検証例 – 問題点 – プログラムをそのまま検査するツールの紹介 モデル検査とは • ハードウェアやソフトウェアの「モデル」が 形式仕様を満足するか検証 • 状態遷移系を網羅的にチェック – 状態の組み合わせが爆発しないように数理 論理学の手法を用いる • 命題の記述には時相論理が使われること が多い SPINとは • Promelaという言語で状態遷移系を記述 – シェルスクリプトに似た文法 • 日本語の本も出版されているくらいメジャー • 命題は時相論理式で記述 – [] p • 今も将来もずっとpが成り立つ – <> p • 将来いずれpが成り立つ –P U q • qが成り立つまではpが成り立つ – ->, <->, !, &&, || 仕様の検証 • 仕様書に漏れがないか確認する • 例として自動販売機の検証を行う 仕様書 • 静的な状態 – コイン投入口、コイン返却口、商品取出口、電源があ る – 使用できる硬貨は100円硬貨のみ – ジュースはAとBの2種類でどちらも1缶100円 – ジュースの在庫量はそれぞれ5つずつ – 貯蔵可能なコインの最大枚数は3枚 – 3つの状態を持つ • 停電状態=電源OFF • 待機状態=電源ON • コイン投入状態=コインが投入されている状態 仕様書(2) • 動的な振舞い – 停電状態において電源がONにされた場合、待機状態に遷移 – 停電状態にコインが投入された場合は • ジュースの在庫がともに0の場合は、投入されたコインをコイン返 却口に返却し、待機状態を維持 • どちらかのジュースの在庫がある場合、投入されたコインを貯蔵し、 コイン投入状態に遷移 – コイン投入状態においてさらにコインが投入された場合は • 貯蔵したコインが3枚の場合、投入されたコインをコイン返却口に 返しコイン投入状態を維持 • 3枚未満の場合は投入されたコインを貯蔵し、コイン投入状態を維 持 – コイン投入状態において購入ボタンが押された場合は… – etc Promelaコード(抜粋) if ::total==Unpower -> if :: power==On -> total=Wait :: (power!=On) && coinIn==On -> rest=1; :: else -> skip fi ::total==Wait -> if :: (power!=Off && coinIn==On && stkA==0 && stkB==0) -> rest=1; :: (power!=Off && coinIn==On && !(stkA==0 && stkB==0)) -> stkC++; total==CoinIn :: (power==Off) -> total=Unpower fi ::total==CoinIn -> if :: (power!=Off && coinIn==On && stkC==3) -> rest=1 LTL式の例 • 停電状態において電源がONにされた場合、待機状態 に遷移する – []((total==Unpower && power==On) -> <>total==Wait) • 待機状態においてコインが投入された場合、いずれか のジュースの在庫がある場合、コインを貯蔵しコイン投 入状態に遷移する – []((total==Wait && coinIn==On && !(stkA==0 && stkB==0)) -> <>(total==CoinIn && stkC==1)) • コインを投入したら、必ず商品を得るかコインが戻ってく る – [](coinIn==On -> <>(outlet!=No || rest!=0)) 検証の結果 • それぞれのLTL式に対して、validかinvalid、ど ちらかの結果が得られる • Invalidであったら、反例が得られ、仕様に漏れ があることがわかる – コイン投入状態でAの在庫が0でBの在庫が1以上の 場合、ボタンAが押されると何も起こらない。したがっ て「必ず商品を得るかコインが戻ってくる」とはいえな い – 電源Offとコイン投入が同時に発生した場合に、電源 Offを優先すると、コイン投入の情報が失われてしま う – ボタンAとボタンBが同時に押されたときの振る舞い も未定義 簡単なCプログラムの検証 • 次のようなプログラムに対して検査を行う – 整数(1から1000まで)を入力する – 入力した整数が6で割り切れれば“OK”を出 力 – 入力した整数が6で割り切れなければ“NG” を出力 Cプログラム #include <stdio.h> main(){ int a; printf(“a = ? >>>”); scanf(“%d”, &a); if(a % 6 == 0){ printf(“OK\n”); }else{ printf(“NG\n”); } } Promelaコード mtype = {OK, NG, NT}; int seisu = 1; int a; mtype prt; active proctype p(){ prt = NT; do :: (seisu <= 1000) -> a=seisu; if ::(a % 6 == 0) -> prt = OK; prt = NT ::else -> prt = NG; prt = NT fi; seisu++ ::else -> break od } LTL式 [](p -> q) • 6で割り切れるときには決してNGにはならない – #define p – #define q (a % 6 == 0) (prt != NG) • 6で割り切れないときには決してOKにはならな い – #define p – #define q (a % 6 != 0) (prt != OK) 問題点 • 元のCプログラムは、1から1000までという限定 した値のみを受け取るようにはできていない • 入力値が網羅的なので、状態組み合わせが爆 発しがち • この程度のテストであれば一般的なテストツー ルで十分 – 複数のスレッド間の並列動作の検証などではかなり 有効 問題点(2) • プログラムをPromelaコードに手作業で変 換するのは面倒 • Promelaコードを美しく書くのは非常に困 難 – 『4日で学ぶモデル検査』に載っている例はコ ピペばかり – XMLのように自動生成して使うもの? Cプログラムをそのまま検査す るツール • BLAST – 述語抽象化法でモデル検査 – 2つの定理証明器 SIMPLYFY と VAMPYREを使用 • SLAM – Microsoft製 – Static Driver Verifierに含まれている – 仕様記述言語SLICによって、APIの使用法が正しい かどうかを検証 Javaプログラムの検査 • JPF(Java Path Finder) – Javaのバイトコードを検証 – ソースコード中にアサーションや抽象化した述語変 数などの注釈を埋め込む • Bandera – LTL式によって検証 – SPIN、SMV、JPFといった外部のモデル検査器を利 用 • Bogor、JNuke
© Copyright 2024 ExpyDoc