"複数回の関数の呼び出しを行うプログラムの実行によって検査対象の記号列が入力または出力されたことを検出する情報処理装置であって、複数の状態と、遷移条件としての記号が対応付けられた状態間の遷移と、前記複数の状態の中の受理状態と、を示す状態遷移情報を記憶する記憶手段と、前記複数回の関数の呼び出しそれぞれが行われるとき、戻り値および引数の少なくとも一方に含まれる記号を抽出する抽出手段と、前記抽出手段で記号が抽出されると、前記複数の状態の中の現在の状態と抽出された記号とから、前記記憶手段に記憶された前記状態遷移情報が示す遷移に従って現在の状態を更新し、更新後の現在の状態が前記受理状態であるか否かに応じて、前記記号列の検出結果の情報を出力する検出手段と、を有する情報処理装置。前記複数回の関数の呼び出しは、入力または出力のストリームを指定して行われ、前記抽出手段は、指定されたストリームの識別情報を更に抽出し、前記検出手段は、前記識別情報に基づいてストリーム毎に現在の状態を管理する、請求項1記載の情報処理装置。前記記号列を示す情報を取得し、前記記号列に含まれる各記号が順に抽出された後の現在の状態が前記受理状態になるように前記状態遷移情報を生成する生成手段、を更に有する請求項1記載の情報処理装置。複数回の関数の呼び出しを行うプログラムの実行によって検査対象の記号列が入力または出力されたことを検出する、コンピュータが実行するソフトウェア検査方法であって、前記複数回の関数の呼び出しそれぞれが行われるとき、戻り値および引数の少なくとも一方に含まれる記号を抽出し、記号が抽出されると、複数の状態と遷移条件としての記号が対応付けられた状態間の遷移と前記複数の状態の中の受理状態とを示す状態遷移情報を記憶する記憶手段を参照して、前記複数の状態の中の現在の状態と抽出された記号とから、現在の状態を更新し、更新後の現在の状態が前記受理状態であるか否かに応じて、前記記号列の検出結果の情報を出力する、ソフトウェア検査方法。複数回の関数の呼び出しを行うプログラムの実行によって検査対象の記号列が入力または出力されたことを検出するソフトウェア検査プログラムであって、コンピュータに、前記複数回の関数の呼び出しそれぞれが行われるとき、戻り値および引数の少なくとも一方に含まれる記号を抽出し、記号が抽出されると、複数の状態と遷移条件としての記号が対応付けられた状態間の遷移と前記複数の状態の中の受理状態とを示す状態遷移情報を記憶する記憶手段を参照して、前記複数の状態の中の現在の状態と抽出された記号とから、現在の状態を更新し、更新後の現在の状態が前記受理状態であるか否かに応じて、前記記号列の検出結果の情報を出力する、処理を実行させるソフトウェア検査プログラム。ところで、あるアプリケーションソフトウェアが、実行中に特定の記号列を入力または出力したか検査したいことがある。例えば、アプリケーションソフトウェアが、機密情報であるパスワードを扱っているか確認するために、passwordという記号列がAPIを通じて入力または出力されたか検査することが考えられる。しかし、アプリケーションソフトウェアが入力または出力のストリームを扱うAPIを利用する場合、ストリームに特定の記号列が含まれるか否かの検査を、どのように行えばよいかが問題となる。入力または出力のストリームでは、検査対象の記号列が複数回の関数呼び出しに分けて入力または出力される可能性がある。例えば、passwordに含まれる記号が、関数呼び出し毎に1字ずつ入力または出力される可能性がある。このため、関数呼び出し単位で戻り値や引数を検査するだけでは、検出漏れが生じ得る。一方、検査のために、アプリケーションソフトウェアがAPIを通じて入力または出力したデータを全てバッファに保持するようにすると、メモリ消費量や検索負荷が増大するという問題がある。本発明はこのような点に鑑みてなされたものであり、入力または出力のストリームの検査を効率的に行うことができる情報処理装置、ソフトウェア検査方法およびソフトウェア検査プログラムを提供することを目的とする。複数回の関数の呼び出しを行うプログラムの実行によって検査対象の記号列が入力または出力されたことを検出する情報処理装置が提供される。当該情報処理装置は、記憶手段と抽出手段と検出手段とを有する。記憶手段は、複数の状態と遷移条件としての記号が対応付けられた状態間の遷移と複数の状態の中の受理状態とを示す状態遷移情報を記憶する。抽出手段は、複数回の関数の呼び出しそれぞれが行われるとき、戻り値および引数の少なくとも一方に含まれる記号を抽出する。検出手段は、抽出手段で記号が抽出されると、複数の状態の中の現在の状態と抽出された記号とから、記憶手段に記憶された状態遷移情報が示す遷移に従って現在の状態を更新し、更新後の現在の状態が受理状態であるか否かに応じて、記号列の検出結果の情報を出力する。また、複数回の関数の呼び出しを行うプログラムの実行によって検査対象の記号列が入力または出力されたことを検出する、コンピュータが実行するソフトウェア検査方法が提供される。当該ソフトウェア検査方法では、複数回の関数の呼び出しそれぞれが行われるとき、戻り値および引数の少なくとも一方に含まれる記号を抽出する。記号が抽出されると、複数の状態と遷移条件としての記号が対応付けられた状態間の遷移と複数の状態の中の受理状態とを示す状態遷移情報を記憶する記憶手段を参照して、複数の状態の中の現在の状態と抽出された記号とから、現在の状態を更新する。更新後の現在の状態が受理状態であるか否かに応じて、記号列の検出結果の情報を出力する。また、コンピュータに実行させるソフトウェア検査プログラムが提供される。上記情報処理装置、ソフトウェア検査方法およびソフトウェア検査プログラムによれば、入力または出力のストリームの検査を効率的に行うことができる。以下、本実施の形態を図面を参照して説明する。[第1の実施の形態]図1は、第1の実施の形態の情報処理装置を示す図である。情報処理装置10は、複数回の関数の呼び出しを行うプログラムの実行によって検査対象の記号列が入力または出力されたことを検出することができる。情報処理装置10は、記憶手段11、抽出手段12および検出手段13を有する。記憶手段11は、RAMRandomAccessMemoryやHDDHardDiskDriveなどの任意の記憶装置を用いて実現できる。抽出手段12および検出手段13は、例えば、CPUCentralProcessingUnitおよびRAMを用いて、ソフトウェア検査プログラムを実行することで実現できる。記憶手段11は、状態遷移情報11aを記憶する。状態遷移情報11aには、複数の状態と、遷移条件としての記号が対応付けられた状態間の遷移と、複数の状態の中の受理状態を示す情報が含まれる。状態遷移情報11aが示す状態遷移関係は、検査対象の記号列に対応している。情報処理装置10は、検査対象の記号列を示す情報が入力されると、当該記号列に含まれる各記号が順に抽出されると現在の状態が受理状態になるように、状態遷移情報11aを生成して記憶手段11に格納するようにしてもよい。抽出手段12は、関数の呼び出しそれぞれが行われるとき、戻り値および引数の少なくとも一方に含まれる記号を抽出する。記号の抽出を行う対象の関数には、入力または出力のストリームを扱うAPIにおいて提供される関数が含まれる。関数は、メソッド、手続きまたはサブルーチンと呼ばれるものであってもよい。抽出手段12は、例えば、入力ストリームの場合、入力された記号を戻り値から抽出し、出力ストリームの場合、出力される記号を引数から抽出する。また、検査対象のプログラムが複数のストリームを扱う可能性がある場合、各ストリームを識別するための識別情報を更に抽出してもよい。検出手段13は、記憶手段11に記憶された状態遷移情報11aを参照して、現在の状態を管理する。検出手段13は、抽出手段12で記号が抽出されると、現在の状態と抽出された記号とから、状態遷移情報11aが示す遷移に従って現在の状態を更新する。検査対象のプログラムが複数のストリームを扱う可能性がある場合、抽出手段12で抽出された識別情報に基づいて、ストリーム毎に現在の状態を管理してもよい。また、検出手段13は、更新後の現在の状態が、状態遷移情報11aが示す受理状態であるか否かに応じて、記号列の検出結果を示す情報を出力する。例えば、現在の状態が受理状態になると、検査対象の記号列が検出されたと判断し、検出された記号列を示す情報を出力する。情報処理装置10は、検出手段13により出力された検出結果の情報を、ファイルに書き込んでもよいし、コンソール画面に表示してもよい。例えば、検査対象の記号列がABCであるとする。また、記号Aを受けて状態0初期状態から状態1に遷移し、記号Bを受けて状態1から状態2へ遷移し、記号Cを受けて状態2から状態3受理状態に遷移することが、状態遷移情報11aに定義されているとする。また、検査対象のプログラムにより、引数として与えられた記号を1字ずつ出力する関数writeが呼び出されるとする。関数呼び出しwriteAが行われると、抽出手段12が引数から記号Aを抽出し、検出手段13が現在の状態を状態0から状態1に更新する。続いて、関数呼び出しwriteBが行われると、抽出手段12が引数から記号Bを抽出し、検出手段13が現在の状態を状態2に更新する。続いて、関数呼び出しwriteCが行われると、抽出手段12が引数から記号Cを抽出し、検出手段13が現在の状態を状態3に更新する。そして、検出手段13は、状態3が受理状態であるため、出力ストリーム内に記号列ABCが検出されたことを示す情報を出力する。第1の実施の形態の情報処理装置10によれば、複数回の関数の呼び出しそれぞれが行われるとき、戻り値および引数の少なくとも一方に含まれる記号を抽出する。記号が抽出されると、複数の状態と遷移条件としての記号が対応付けられた状態間の遷移と複数の状態の中の受理状態とを示す状態遷移情報11aを記憶する記憶手段11を参照して、複数の状態の中の現在の状態と抽出された記号とから、現在の状態を更新する。更新後の現在の状態が受理状態であるか否かに応じて、記号列の検出結果の情報を出力する。これにより、入力または出力のストリームの検査を効率的に行うことができる。情報処理装置10は、複数回の関数呼び出しを通して状態遷移情報11aに基づく状態の管理を行うため、複数回に分けて入力または出力された記号列を検出できる。また、抽出された記号に基づいて現在の状態を順次更新すればよく、入力または出力された記号をバッファに記憶しておかなくてもよいため、メモリ消費量や検索負荷を抑制できる。また、関数呼び出しを監視することで記号列を検出するため、操作される対象ファイルなどを予め具体的に特定しなくても、検査を行うことが可能となる。また、情報処理装置10は、入力または出力のストリーム毎に現在の状態を管理することで、複数のストリームを扱うプログラムを適切に検査することができる。例えば、記号を1字ずつ出力するためのストリーム1,2が生成され、ストリーム1によって記号列ABDが出力され、ストリーム2によって記号列CEFが出力されるとする。ストリーム1,2を区別しないと、各記号が出力されるタイミング次第では、記号列ABCが出力されたと判断されてしまう可能性がある。一方、ストリーム毎に現在の状態を管理することで、記号列ABDと記号列CEFを区別できる。[第2の実施の形態]次に、第2の実施の形態を説明する。第2の実施の形態に係る情報処理装置は、Java登録商標などのプログラミング言語を用いて記述されたアプリケーションプログラムを実行する。また、この情報処理装置は、アプリケーションプログラムの実行中、入力または出力のストリームを扱うAPIの呼び出しを検出し、ストリームに含まれる文字列を検査する。API呼び出しが行われたときに制御権を取得して検査などの処理が行われるようにすることを、APIフッキングと呼ぶことがある。以下の説明では、Javaを用いて記述されたプログラムの例を挙げている。ただし、第2の実施の形態のソフトウェア検査方法は、適用対象を特定のプログラミング言語に限定するものではない。図2は、情報処理装置のハードウェア例を示すブロック図である。情報処理装置100は、CPU101、RAM102、HDD103、画像信号処理部104、入力信号処理部105、ディスクドライブ106および通信部107を有する。上記ユニットは、情報処理装置100内でバスに接続されている。CPU101は、情報処理を制御する演算装置である。CPU101は、HDD103に記憶されたプログラムやデータの少なくとも一部を読み出し、RAM102に展開してプログラムを実行する。RAM102は、CPU101が扱うプログラムやデータを一時的に記憶する揮発性メモリである。ただし、情報処理装置100は、他の種類のメモリを備えてもよい。HDD103は、OSプログラムやアプリケーションプログラムなどのプログラム、および、CPU101の処理に用いられるデータを記憶する不揮発性の記憶装置である。HDD103は、内蔵の磁気ディスクに対し読み書きを行う。ただし、情報処理装置100は、他の種類の不揮発性の記憶装置を備えてもよい。画像信号処理部104は、CPU101の命令に従って、情報処理装置100に接続されたディスプレイ21に画像を表示する。ディスプレイ21として、例えば、CRTCathodeRayTubeディスプレイや液晶ディスプレイを用いることができる。入力信号処理部105は、情報処理装置100に接続された入力デバイス22から入力信号を取得し、CPU101に出力する。入力デバイス22として、例えば、マウスなどのポインティングデバイスやキーボードを用いることができる。ディスクドライブ106は、記録媒体23に記録されたプログラムやデータを読み取る駆動装置である。記録媒体23として、例えば、フレキシブルディスクFD:FlexibleDiskなどの磁気ディスク、CDCompactDiscやDVDDigitalVersatileDiscなどの光ディスク、光磁気ディスクMO:MagnetoOpticaldiskを用いることができる。ディスクドライブ106は、例えば、CPU101の命令に従って、記録媒体23から読み取ったプログラムやデータをRAM102またはHDD103に出力する。通信部107は、ネットワーク24に接続して通信を行う通信インタフェースである。ネットワーク24への接続方法は、有線でも無線でもよい。すなわち、通信部107は、有線通信インタフェースでも無線通信インタフェースでもよい。図3は、オートマトンの例を示す図である。情報処理装置100は、オートマトンを用いて、入力または出力のストリームに含まれる文字列の中から特定の文字列を検出する。オートマトンは、仮想的な自動機械であり、複数の状態の間の遷移関係を定義している。第2の実施の形態では、オートマトンとして、エイホコラシックアルゴリズムに従って生成される決定性有限オートマトンを用いる場合を考える。エイホコラシックアルゴリズムについては、例えば、文献AlfredVAhoandMargaretJCorasickEfficientStringMatchingAnAidtoBibliographicSearchCommunicationsoftheACMVol18Number6pp333340June1975に記載されている。ただし、文字列の検出は、他の種類のオートマトンを用いて実現することも可能である。文字列passwordおよびassetを検出することを考える。図3のオートマトンの例では、状態0~13の14個の状態が定義されている。状態0~13のうち、状態0が初期状態であり、状態8,13が受理状態である。状態0から開始し、オートマトンに文字が入力されると遷移が発生する。状態8は、文字列passwordが検出されたことを意味する。状態13は、文字列assetが検出されたことを意味する。遷移には、通常遷移図3の実線の矢印とfailure遷移図3の点線の矢印であり、suffixリンクと呼ぶことがあるが含まれる。通常遷移が発生する条件は、当該遷移に対応付けられた文字が入力されたことである。failure遷移が発生する条件は、入力された文字が何れの通常遷移の条件にも合致しないことである。failure遷移は、条件に合致する通常遷移が見つかるまで連鎖的に発生する。すなわち、オートマトンに文字が入力されると、failure遷移が発生せずに通常遷移が1回発生するか、または、1回以上のfailure遷移が発生した後に通常遷移が1回発生する。例えば、状態4のときwが入力されると、通常遷移に従って、現在の状態が状態5に遷移する。状態4のときeが入力されると、failure遷移に従って、現在の状態が状態11に遷移し、更に通常遷移に従って、状態12に遷移する。状態4のときw,e以外の文字が入力されると、2回のfailure遷移に従って、現在の状態が状態0に戻る。なお、図3では、状態0,2,3,4以外の状態から状態0へのfailure遷移の記載を省略している。オートマトンにfailure遷移を定義することで、ストリームの中から複数の文字列を効率的に検出することができる。例えば、ストリームから抽出された文字列がpassである場合、現在の状態は状態4である。この時点において、検出が期待される文字列はpasswordである。しかし、次にeが抽出され、ストリームから抽出された文字列がpasseになると、現在の状態が状態12に遷移する。この時点において、検出が期待される文字列がassetに変化する。図4は、情報処理装置の機能を示すブロック図である。情報処理装置100には、CPU101がプログラムを実行することで、プログラム記憶部110、状態情報記憶部120、検出情報記憶部130、APIフッキング部140、オートマトン生成部150、解析部160および検出部170が実現される。ただし、上記ユニットの一部または全部を専用の電子回路として実現することも可能である。プログラム記憶部110は、検査対象のプログラムを記憶する。例えば、バイトコードを含むJavaのクラスファイルを記憶する。プログラム記憶部110は、例えば、RAM102またはHDD103上に確保された記憶領域として実現できる。状態情報記憶部120は、生成されたオートマトンに関する状態遷移情報を記憶する。状態遷移情報には、通常遷移を示す情報、failure遷移を示す情報、受理状態を示す情報、および、現在の状態を示す情報が含まれる。状態情報記憶部120は、例えば、RAM102またはHDD103上に確保された記憶領域として実現できる。検出情報記憶部130は、文字列の検出結果に関する検出情報を記憶する。検出情報には、入力または出力のストリームから検出された文字列や、当該ストリームを扱うAPIを示す情報が含まれる。検出情報記憶部130は、例えば、RAM102またはHDD103上に確保された記憶領域として実現できる。APIフッキング部140は、ユーザ操作によりプログラムを実行するコマンドが入力されると、コマンドで指定されたプログラムをプログラム記憶部110から取得する。そして、プログラムの中から所定のAPI呼び出しを行うコードを検索し、API呼び出しの際に、呼び出されるAPIの処理に加えて解析部160による処理が実行されるようにコードを書き換える。例えば、APIフッキング部140は、ReaderやWriterなどのAPIのメソッドを呼び出すコードを、解析部160に相当するプログラムを呼び出すコードに書き換える。または、メソッド呼び出しのコードの直後に、解析部160に相当するプログラムが実行されるようなコードを挿入する。オートマトン生成部150は、ユーザ操作により検査対象の文字列を示すパターン情報が入力されると、検査対象の文字列に対応するオートマトンを生成し、状態遷移情報を状態情報記憶部120に格納する。パターン情報は、例えば、プログラムを実行するコマンドと併せて入力される。検査対象の文字列は、正規表現など、任意の表現形式で記載することができる。例えば、検査対象の文字列がpasswordとassetである場合、password|assetというテキストが入力される。解析部160は、APIフッキング部140により書き換えられたプログラムから呼び出される。解析部160は、ストリームを扱うAPIが呼び出された際、API呼び出しを解析し、戻り値または引数に含まれる文字とストリームを識別するためのストリーム識別子とを抽出し、検出部170に出力する。文字およびストリーム識別子の抽出方法は、APIの種類によって異なる。解析部160は、APIの種類毎に、API呼び出しから文字およびストリーム識別子を抽出するモジュールを備える。例えば、解析部160は、Reader解析部161とWriter解析部162を有する。Reader解析部161は、Readerクラスのreadメソッドが呼び出されると、入力された文字を戻り値から抽出し、Readerクラスのインスタンスオブジェクトの識別子を抽出する。Writer解析部162は、Writerクラスのwriteメソッドが呼び出されると、出力された文字を引数から抽出し、Writerクラスのインスタンスの識別子を抽出する。なお、APIフッキング部140がAPIのメソッドを呼び出すコードを書き換える場合、解析部160は、検査対象のプログラムに代わってAPIのメソッドを呼び出す。例えば、Reader解析部161は、Readerクラスのreadメソッドを呼び出し、その後に戻り値を解析する。一方、Writer解析部162は、Writerクラスのwriteメソッドを呼び出す前または呼び出した後に、引数を解析する。検出部170は、ストリーム毎に現在の状態を管理し、検査対象の文字列が検出されたか判断する。検出部170は、解析部160から文字とストリーム識別子を取得すると、ストリーム識別子に対応する現在の状態を検索する。そして、状態情報記憶部120に記憶された状態遷移情報に基づいて、現在の状態と取得した文字から、現在の状態を更新する。検出部170は、更新後の現在の状態が受理状態であれば、検査対象の文字列が検出されたと判断し、検出情報を生成して検出情報記憶部130に出力する。ただし、検出部170は、検出情報を、コンソール画面などのユーザ操作画面に表示してもよい。なお、状態情報記憶部120は、第1の実施の形態の記憶手段11の一例である。APIフッキング部140および解析部160は、第1の実施の形態の抽出手段12の一例である。検出部170は、第1の実施の形態の検出手段13の一例である。図5は、通常遷移テーブルの例を示す図である。通常遷移テーブル121は、オートマトン生成部150によって生成され、状態情報記憶部120に格納される。通常遷移テーブル121は、前状態、入力および後状態の項目を含む。前状態の項目には、遷移前の状態を示す状態ID図3の例では、0~13の何れかが登録される。入力の項目には、遷移条件である文字または1またはそれ以上の文字を含む論理式が登録される。後状態の項目には、遷移後の状態を示す状態IDが登録される。前状態の項目が示す状態のときに入力の項目に合致する文字が入力されると、前状態の項目が示す状態から後状態の項目が示す状態への通常遷移が発生する。図5のテーブルの例は、図3のオートマトンの例に対応し、14個の通常遷移を含む。なお、通常遷移テーブル121は、ハッシュテーブルとして実装してもよい。例えば、JavaのHashMapクラスを用いることが考えられる。その場合、ハッシュテーブルには、前状態と入力の組がキーとして登録され、後状態がエントリとして登録される。ハッシュテーブルは、例えば、RAM102上に確保された領域に記憶される。図6は、failure遷移テーブルの例を示す図である。failure遷移テーブル122は、オートマトン生成部150によって生成され、状態情報記憶部120に格納される。failure遷移テーブル122は、前状態および後状態の項目を含む。通常遷移テーブル121と同様、前状態の項目には、遷移前の状態を示す状態IDが登録される。後状態の項目には、遷移後の状態を示す状態IDが登録される。現在の状態と解析部160で抽出された文字の組に対応する通常遷移が、通常遷移テーブル121に登録されていないとき、現在の状態から後状態の項目が示す状態へのfailure遷移が発生する。図6のテーブルの例は、13個のfailure遷移を含む。なお、failure遷移テーブル122は、通常遷移テーブル121と同様、ハッシュテーブルとして実装してもよい。その場合、ハッシュテーブルには、前状態がキーとして登録され、後状態がエントリとして登録される。図7は、受理状態テーブルの例を示す図である。受理状態テーブル123は、オートマトン生成部150によって生成され、状態情報記憶部120に格納される。受理状態テーブル123は、受理状態および文字列の項目を含む。受理状態の項目には、受理状態を示す状態IDが登録される。文字列の項目には、現在状態が受理状態になったときに検出されたと判断される、検査対象の文字列が登録される。例えば、図3のオートマトンの場合、受理状態=8,文字列=passwordという情報、および、受理状態=13,文字列=assetという情報が、受理状態テーブル123に登録される。なお、受理状態テーブル123は、通常遷移テーブル121と同様に、ハッシュテーブルとして実装してもよい。その場合、ハッシュテーブルには、受理状態がキーとして登録され、文字列がエントリとして登録される。図8は、状態管理テーブルの例を示す図である。オートマトン生成部150によって、空の状態管理テーブル124が生成され、状態情報記憶部120に格納される。また、検出部170によって、状態情報記憶部120に記憶された状態管理テーブル124が更新される。状態管理テーブル124は、ストリーム識別子および状態の項目を含む。ストリーム識別子の項目には、解析部160で抽出された識別子が登録される。図8の例では、ストリーム識別子として、Javaクラスのインスタンスの識別子を用いている。状態の項目には、現在の状態を示す状態IDが登録される。例えば、検査対象のプログラムによってReaderやWriterなどのクラスのインスタンスが生成され、当該インスタンスを指定してreadやwriteなどのメソッドが呼び出されると、状態管理テーブル124にインスタンスの識別子が追加される。また、当該メソッドが呼び出される毎に、現在の状態が更新される。状態管理テーブル124は、検査対象のプログラムの実行が終了すると破棄される。ただし、検査対象のプログラムの実行中に、不要となったストリームの情報を状態管理テーブル124から削除するようにしてもよい。例えば、インスタンスを指定してストリームを閉じるメソッド例えば、closeが呼び出されたときに、当該インスタンスに対応する情報を状態管理テーブル124から削除するようにする。または、ガーベッジコレクションの機能を利用して、インスタンスが消滅すると、当該インスタンスに依存する情報が状態管理テーブル124から自動的に削除されるようする。図9は、プログラム制御の手順例を示すフローチャートである。ステップS1オートマトン生成部150は、検査対象となる1またはそれ以上の文字列を示すパターン情報例えば、正規表現により文字列のパターンを記載したものを取得する。そして、オートマトン生成部150は、パターン情報が示す文字列を検出するためのオートマトンを生成する。ステップS2APIフッキング部140は、検査対象のプログラムの中のコード例えば、Javaのバイトコードを書き換えることで、入力または出力のストリームを扱うAPIが呼び出される際に、解析部160が制御権を取得できるようにする。ステップS3情報処理装置100は、APIフッキング部140により書き換えられたプログラムの実行を開始する。例えば、書き換えられたプログラムをRAM102上の適切な領域に展開し、当該プログラムのmainメソッドを呼び出す。ステップS4情報処理装置100は、入力または出力のストリームを扱うAPIが呼び出されたか判断する。APIが呼び出された場合、処理をステップS5に進める。呼び出されていない場合、処理をステップS6に進める。ステップS5解析部160は、API呼び出しにおける戻り値または引数から、当該APIを通して入力または出力される文字を抽出する。検出部170は、オートマトンと抽出された文字とに基づいて、ストリームの現在の状態を更新する。検出部170は、更新後の現在の状態が受理状態であれば、検出された文字列を示す検出情報を出力する。ステップS6情報処理装置100は、検査対象のプログラムの実行が終了したか判断する。終了した場合、文字列の検出の処理も終了する。終了していない場合、処理をステップS4に進める。なお、検査対象のプログラムの実行が終了するとき、情報処理装置100は、状態情報記憶部120に記憶された状態遷移情報を消去してもよい。以下では、ステップS1で実行されるオートマトン生成の処理、ステップS2で実行されるAPIフッキングの処理、および、ステップS5で実行される文字列検出の処理それぞれについて、更に説明を加える。図10は、オートマトン生成の手順例を示すフローチャートである。図10に示す処理は、前述のステップS1の中で実行される。なお、図10に示すオートマトンの生成手順は一例であり、他の手順によってオートマトンを生成することも可能である。ステップS11オートマトン生成部150は、パターン情報から1またはそれ以上の文字列を抽出する。例えば、正規表現で記載された文字列パターンpassword|assetから、文字列passwordとassetを抽出する。ステップS12オートマトン生成部150は、初期状態状態0を追加する。ステップS13オートマトン生成部150は、ステップS11で抽出した1またはそれ以上の文字列の中から、文字列を1つ選択する。ステップS14オートマトン生成部150は、現在の状態を状態0とする。ステップS15オートマトン生成部150は、ステップS13で選択した文字列の先頭側から、文字を1つ抽出する。ステップS16オートマトン生成部150は、現在の状態が遷移元でありステップS15で抽出した文字が遷移条件である通常遷移が存在するか判断する。存在する場合、処理をステップS18に進める。存在しない場合、処理をステップS17に進める。ステップS17オートマトン生成部150は、オートマトンに新たな状態を追加すると共に、現在の状態から当該新たな状態への通常遷移を追加する。また、追加した通常遷移に、ステップS15で抽出した文字を遷移条件として対応付ける。ステップS18オートマトン生成部150は、現在の状態を、ステップS16で見つかった通常遷移の遷移先、または、ステップS17で追加した状態に遷移させる。ステップS19オートマトン生成部150は、ステップS15で抽出した文字が、文字列の末尾の文字であるか判断する。末尾の文字である場合、処理をステップS20に進める。末尾の文字でない場合、処理をステップS15に進める。ステップS20オートマトン生成部150は、現在の状態を受理状態に指定する。ステップS21オートマトン生成部150は、ステップS13で選択した文字列が最後の文字列であるか判断する。最後の文字列である場合、処理をステップS22に進める。最後の文字列でない場合、処理をステップS13に進める。ステップS22オートマトン生成部150は、通常遷移として、状態0から状態0に遷移する自己遷移をオートマトンに追加する。また、当該自己遷移に、他の何れの通常遷移の遷移条件にも合致しないことを示す論理式を対応付ける。例えば、文字pが対応付けられた状態0から状態1への通常遷移と、文字aが対応付けられた状態0から状態9への通常遷移とが存在する場合、notpまたはaという論理式が、遷移条件として自己遷移に対応付けられる。図11は、オートマトン生成の手順例を示すフローチャート続きである。図11に示す処理は、図10に示す処理に続いて、前述のステップS1の中で実行される。なお、図11に示すオートマトンの生成手順は一例であり、他の手順によってオートマトンを生成することも可能である。ステップS23オートマトン生成部150は、各状態の深さを算出する。深さは、初期状態状態0を起点として通常遷移を辿った場合のホップ数とする。図3の例の場合、状態0の深さは0、状態8の深さは8、状態13の深さは5である。ステップS24オートマトン生成部150は、深さ1の状態図3の例の場合、状態1,9から状態0へのfailure遷移を、オートマトンに追加する。ステップS25オートマトン生成部150は、変数n=2に設定する。ステップS26オートマトン生成部150は、深さnの状態Snを選択する。以下のステップS27~S30の処理を、状態Snそれぞれについて実行する。ステップS27オートマトン生成部150は、前状態=Sn1,入力=x,後状態=Snである通常遷移を抽出するSn1は深さn-1の状態であり、xは任意の1文字である。また、オートマトン生成部150は、前状態=Sn1,後状態=Stであるfailure遷移を抽出するStは任意の状態である。ステップS28オートマトン生成部150は、前状態=St,入力=x,後状態=Suである通常遷移が存在するか判断するSuは任意の状態である。存在する場合、処理をステップS29に進める。存在しない場合、処理をステップS30に進める。ステップS29オートマトン生成部150は、状態Snから状態Suへのfailure遷移を、オートマトンに追加する。ステップS30オートマトン生成部150は、状態Snから状態0へのfailure遷移を、オートマトンに追加する。ステップS31オートマトン生成部150は、ステップS29またはステップS30で追加したfailure遷移の前状態と後状態の間で、受理状態を統合する。ステップS32オートマトン生成部150は、nを1だけ増加させる。ステップS33オートマトン生成部150は、nがオートマトンの深さの最大値図3の例の場合は8より大きいか判断する。条件を満たす場合、処理を終了する。条件を満たさない場合、処理をステップS26に進める。以上のステップS11~S33の処理により、オートマトン生成部150は、オートマトンを生成することができる。次に、APIフッキングの実装例を説明する。図12は、APIフッキングの第1の方法を示す図である。第1の方法では、解析部160が、検査対象のプログラムに代わってAPI呼び出しを行う。例えば、APIフッキング部140は、Javaのinstrumentation機能を用いて、検査対象のプログラムのロード時に、ReaderクラスまたはWriterクラスのメソッドを呼び出す命令invokevirtual,invokespecial,invokestatic,invokeinterfaceなどを検索する。そして、APIフッキング部140は、検索した命令を、Reader解析部161またはWriter解析部162を呼び出す命令に書き換える。Reader解析部161は、検索対象のプログラムからの呼び出しの際に、Readerクラスのインスタンスへの参照を取得する。そして、当該インスタンスを指定して、readメソッドを呼び出す。Reader解析部161は、readメソッドの戻り値から文字を抽出し、抽出した文字を検出部170に出力する。また、Readerクラスのインスタンスの識別子を、ストリーム識別子として検出部170に出力する。Writer解析部162は、検索対象のプログラムからの呼び出しの際に、Writerクラスのインスタンスへの参照と引数を取得する。そして、当該インスタンスを指定し、当該引数を用いてwriteメソッドを呼び出す。Writer解析部162は、引数から文字を抽出し、抽出した文字を検出部170に出力する。また、Writerクラスのインスタンスの識別子を、ストリーム識別子として検出部170に出力する。なお、API呼び出しのコードを書き換える方法として、文献GalenHuntandDougBrubacherDetoursBinaryInterceptionofWin32FunctionsProceedingsofthe3rdUSENIXWindowsNTSymposiumJuly1999に記載された方法を用いてもよい。図13は、APIフッキングの第1の実装例を示す図である。図13に示すようなプログラムによって、解析部160を実現できる。Analyzerクラスが、解析部160に対応する。AnalyzerクラスのreadメソッドがReader解析部161に対応し、writeメソッドがWriter解析部162に対応する。また、Detectorクラスが、検出部170に対応する。検査対象のプログラムでは、Readerクラスのreadメソッドを呼び出すコードが、Analyzerクラスのreadメソッドを呼び出すコードに書き換えられる。Analyzerクラスのreadメソッドが呼び出されると、検査対象のプログラムに代わってReaderクラスのreadメソッドが呼び出され、文字streamDataとストリーム識別子streamIDが抽出される。また、検査対象のプログラムでは、Writerクラスのwriteメソッドを呼び出すコードが、Analyzerクラスのwriteメソッドを呼び出すコードに書き換えられる。Analyzerクラスのwriteメソッドが呼び出されると、検査対象のプログラムに代わってWriterクラスのwriteメソッドが呼び出され、文字とストリーム識別子が抽出される。なお、Writerクラスのwriteメソッドの呼び出しを、文字とストリーム識別子の抽出の後に行うようにしてもよい。図14は、APIフッキングの第2の方法を示す図である。第2の方法では、検査対象のプログラムによってAPI呼び出しが行われた後に、解析部160の処理が行われる。例えば、APIフッキング部140は、検査対象のプログラムのロード時に、ReaderクラスまたはWriterクラスのメソッドを呼び出す命令を検索する。そして、検索した命令の直後にReader解析部161またはWriter解析部162の処理が実行されるように、検査対象のプログラムにコードを挿入する。コード挿入は、BCELByteCodeEngineeringLibraryなどのライブラリを用いて実現してもよい。また、AspectJのLoadTimeWeaving機能を利用して実現してもよい。Reader解析部161は、検査対象のプログラムによってReaderクラスのreadメソッドが呼び出された直後に、戻り値とReaderクラスのインスタンスへの参照を取得する。Reader解析部161は、戻り値から文字を抽出し、抽出した文字を検出部170に出力する。また、Readerクラスのインスタンスの識別子を、ストリーム識別子として検出部170に出力する。Writer解析部162は、検査対象のプログラムによってWriterクラスのwriteメソッドが呼び出された直後に、引数とWriterクラスのインスタンスへの参照を取得する。Writer解析部162は、引数から文字を抽出し、抽出した文字を検出部170に出力する。また、Writerクラスのインスタンスの識別子を、ストリーム識別子として検出部170に出力する。図15は、APIフッキングの第2の実装例を示す図である。図15に示すようなプログラムによって、APIフッキング部140および解析部160を実現できる。図15のプログラム例では、Javaのinstrumentation機能とAspectJの機能を利用している。Agentクラスのpremainメソッドが実行されると、検査対象のプログラムから、アノテーションAfterReturningのpointcutの条件に合致するコードが検索される。図15の例では、Readerクラスを継承しているクラスのreadメソッドを呼び出すコードが検索される。そして、検索されたコードの直後に、アノテーションAfterReturningが付与されたメソッド図15の例では、readメソッドを呼び出すコードが挿入される。次に、文字列検出の処理を説明する。図16は、文字列検出の手順例を示すフローチャートである。図16に示す処理は、前述のステップS5の中で実行される。ステップS41解析部160は、ストリーム識別子を抽出する。また、戻り値または引数から、APIを通して入力または出力される文字を抽出する。ステップS42検出部170は、解析部160で抽出されたストリーム識別子に対応する現在の状態を、状態管理テーブル124から検索する。ステップS43検出部170は、ストリーム識別子に対応する現在の状態が、状態管理テーブル124に登録されているか判断する。登録されている場合、処理をステップS45に進める。登録されていない場合、処理をステップS44に進める。ステップS44検出部170は、ストリーム識別子に対応付けて、初期状態を示す状態IDを状態管理テーブル124に登録する。ステップS45検出部170は、ストリームの現在の状態および解析部160で抽出された文字に対応する通常遷移を、通常遷移テーブル121から検索する。そして、該当する通常遷移が存在するか判断する。存在する場合、処理をステップS47に進める。存在しない場合、処理をステップS46に進める。ステップS46検出部170は、ストリームの現在の状態に対応するfailure遷移を、failure遷移テーブル122から検索する。そして、状態管理テーブル124に登録された現在の状態を、failure遷移後の状態に書き換える。その後、処理をステップS45に進める。ステップS47検出部170は、状態管理テーブル124に登録された現在の状態を、ステップS45で検索された通常遷移後の状態に書き換える。ステップS48検出部170は、受理状態テーブル123を参照して、ストリームの現在の状態が受理状態であるか判断する。受理状態である場合、処理をステップS49に進める。受理状態でない場合、処理を終了して次のAPI呼び出しを待つ。ステップS49検出部170は、受理状態テーブル123を参照して、検出された文字列を判断する。そして、検出情報を生成して検出情報記憶部130に格納する。図17は、検出情報の例を示す図である。検出部170が生成する検出情報には、例えば、検出された文字列、当該文字列が含まれるストリームの識別子、呼び出されたAPIの情報、および、検査対象プログラム中のAPI呼び出しを記載したコードの位置が含まれる。文字列は、受理状態テーブル123から取得できる。ストリーム識別子は、状態管理テーブル124から取得できる。API情報およびコード位置は、例えば、ThreadクラスのgetStackTraceメソッドを呼び出すことで取得できる。例として、検査対象のプログラムによりReaderクラスのインスタンスが2つ生成されオブジェクトA,B、以下の順序で文字が取得された場合を考える。1オブジェクトAを通して文字pを取得する。2オブジェクトBを通して文字aを取得する。3オブジェクトAを通して文字aを取得する。4オブジェクトBを通して文字pを取得する。5オブジェクトAを通して文字sを取得する。6オブジェクトAを通して文字sを取得する。7オブジェクトAを通して文字eを取得する。8オブジェクトAを通して文字tを取得する。1番目の文字が抽出されると、検出部170は、まずオブジェクトAの識別子と状態0を状態管理テーブル124に登録する。次に、入力pによる通常遷移が発生するため、検出部170は、オブジェクトAの状態を状態0から状態1に更新する。状態1は受理状態でないため、検出情報を出力せずに次の文字が抽出されるのを待つ。2番目の文字が抽出されると、検出部170は、まずオブジェクトBの識別子と状態0を状態管理テーブル124に登録する。次に、入力aによる通常遷移が発生するため、検出部170は、オブジェクトBの状態を状態0から状態9に更新する。状態9は受理状態でないため、検出情報を出力せずに次の文字が抽出されるのを待つ。3番目の文字が抽出されると、検出部170は、状態管理テーブル124を参照して、オブジェクトAの状態が状態1であると判断する。入力aによる通常遷移が発生するため、検出部170は、オブジェクトAの状態を状態1から状態2に更新する。状態2は受理状態でないため、検出情報を出力せずに次の文字が抽出されるのを待つ。4番目の文字が抽出されると、検出部170は、状態管理テーブル124を参照して、オブジェクトBの状態が状態9であると判断する。ここではfailure遷移が発生するため、検出部170は、オブジェクトBの状態を状態9から状態0に更新する。更に、入力pによる通常遷移が発生するため、検出部170は、オブジェクトBの状態を状態0から状態1に更新する。状態1は受理状態でないため、検出情報を出力せずに次の文字が抽出されるのを待つ。5番目の文字が抽出されると、検出部170は、状態管理テーブル124を参照して、オブジェクトAの状態が状態2であると判断する。入力sによる通常遷移が発生するため、検出部170は、オブジェクトAの状態を状態2から状態3に更新する。状態3は受理状態でないため、検出情報を出力せずに次の文字が抽出されるのを待つ。6番目の文字が抽出されると、検出部170は、状態管理テーブル124を参照して、オブジェクトAの状態が状態3であると判断する。入力sによる通常遷移が発生するため、検出部170は、オブジェクトAの状態を状態3から状態4に更新する。状態4は受理状態でないため、検出情報を出力せずに次の文字が抽出されるのを待つ。7番目の文字が抽出されると、検出部170は、状態管理テーブル124を参照して、オブジェクトAの状態が状態4であると判断する。ここではfailure遷移が発生するため、検出部170は、オブジェクトAの状態を状態4から状態11に更新する。更に、入力eによる通常遷移が発生するため、検出部170は、オブジェクトAの状態を状態11から状態12に更新する。状態12は受理状態でないため、検出情報を出力せずに次の文字が抽出されるのを待つ。8番目の文字が抽出されると、検出部170は、状態管理テーブル124を参照して、オブジェクトAの状態が状態12であると判断する。入力tによる通常遷移が発生するため、検出部170は、オブジェクトAの状態を状態12から状態13に更新する。状態13は受理状態であるため、検出部170は、検出情報を生成し出力する。なお、オブジェクトAを通して更に文字が取得された場合、状態13を遷移元とする通常遷移が存在しないため、failure遷移が発生して状態0に戻ることになる。以上の説明では、文字を1字ずつ入力または出力するAPIの例を示したが、1回のメソッド呼び出しで複数の文字を入力または出力できるAPIについても、同様の方法で文字列の検出を行うことができる。その場合、例えば、検出部170は、抽出された複数の文字を順にオートマトンに入力すればよい。また、以上の説明では、文字列を検出する例を示したが、文字以外の記号を含む記号列やバイトパターンを検出してもよい。また、情報処理装置100は、ストリームで用いられている文字コードを判断し、文字コードに応じて、検出するバイトパターンを決定するようにしてもよい。第2の実施の形態の情報処理装置100によれば、入力または出力のストリームの検査を効率的に行うことができる。複数回のAPI呼び出しを通してオートマトンに基づいて状態管理を行うため、複数回に分けて入力または出力される文字列を検出できる。また、抽出された文字に基づいて現在の状態を順次更新すればよく、入力または出力された文字列をバッファに記憶しておかなくてもよいため、メモリ消費量や検索負荷を抑制できる。また、API呼び出しを監視することで文字列を検出するため、ファイルなどの操作対象を予め具体的に特定しなくても、検査を行うことが可能となる。また、入力または出力のストリーム毎に現在の状態を管理するため、複数のストリームを適切に検査できる。なお、前述の通り、第2の実施の形態のソフトウェア検査方法は、コンピュータとしての能力を備える情報処理装置100に、ソフトウェア検査プログラムを実行させることで実現できる。当該プログラムは、コンピュータ読み取り可能な記録媒体例えば、記録媒体23に記録しておくことができる。記録媒体として、例えば、磁気ディスク、光ディスク、光磁気ディスク、半導体メモリなどを使用できる。磁気ディスクには、HDDおよびFDが含まれる。光ディスクには、CD、CD-RRecordable/RWRewritable、DVDおよびDVD-R/RWが含まれる。プログラムを流通させる場合、例えば、当該プログラムを記録した可搬記録媒体が提供される。また、プログラムを他の情報処理装置の記憶装置に格納しておき、ネットワーク24経由で当該プログラムを配布することもできる。情報処理装置100は、例えば、可搬記録媒体に記録されたプログラムまたは他の情報処理装置から受信したプログラムを、HDD103などの記憶装置に格納し、記憶装置からプログラムを読み込んで実行する。ただし、可搬型記録媒体からプログラムを直接読み込んで実行してもよい。また、他の情報処理装置からプログラムを受信する毎に逐次、受信したプログラムを実行してもよい。"