(57)【要約】【課題】メモリアクセス先のアドレスを任意の整数演算により算出する処理を含むプログラムに対しても境界検査を実施することができるように機能を拡張することができる検査用プログラム生成装置を提供する。【解決手段】書き換え部４は、プログラム記憶部２が記憶する検査用プログラムに記述されるポインタ変数を、ポインタ変数が示すアドレスを指すポインタ値と、ポインタ変数が示すアドレスに先頭アドレスを示す識別番号を加算した検査値とを格納する拡張ポインタ構造体に書き換える。次に、書き換え部４は、検査用プログラムに、拡張ポインタ構造体の検査値からポインタ値を減じることで、アクセス対象となるメモリ領域の識別番号を取得する命令記述を追加する。【選択図】図１
2010277302.tif 000002
【特許請求の範囲】
【請求項１】
検査対象プログラムから当該検査対象プログラムのメモリアクセスのアドレス範囲を検査する検査用プログラムを生成する検査用プログラム生成装置であって、
前記検査対象プログラムで用いられるメモリ領域の各々に対して識別番号を割り当てる命令記述を当該検査対象プログラムに追加し、
前記検査対象プログラムに含まれるポインタ変数を、当該ポインタ変数の参照先アドレスを示すポインタ値、及び当該ポインタ値と前記ポインタ変数の参照先メモリ領域に割り当てられた識別番号とを加算した値を示す検査値で構成される拡張ポインタ構造体に変換し、前記ポインタ変数に対してなされる命令記述を、前記拡張ポインタ構造体のポインタ値に対してなされる命令記述に変換し、
前記検査対象プログラムに含まれる、ポインタ変数を用いたメモリアクセスを行う命令記述の前に、前記拡張ポインタ構造体の検査値から前記ポインタ値を減じた値を算出させ、アクセス対象となるメモリ領域の識別番号が当該値と等しいメモリ領域の範囲に含まれるか否かを判定することで境界検査を行う命令記述を追加する書き換え手段と、
前記書き換え手段によって命令記述の書き換えが行われた検査対象プログラムを検査用プログラムとして出力する出力手段と、
を備えることを特徴とする検査用プログラム生成装置。
【請求項２】
前記書き換え手段は、
前記検査対象プログラムのメモリ領域に対して識別番号を割り当てる命令記述の後に、当該割り当てられた識別番号に紐づけて当該メモリ領域のアドレス範囲をメモリ領域テーブルに登録する命令記述を追加し、
前記検査対象プログラムの前記メモリ領域テーブルに追加されたメモリ領域が解放される命令記述の前に、当該解放するメモリ領域をメモリ領域テーブルから削除する命令記述を追加し、
前記検査対象プログラムに追加する境界検査を行う命令記述は、前記拡張ポインタ構造体の検査値から前記ポインタ値を減じた値を算出し、前記メモリ領域テーブルの中から当該値と等しい識別番号のメモリ領域の範囲を取得し、メモリアクセスを行うアドレスが当該範囲に含まれるか否かを判定させる命令記述である、
ことを特徴とする請求項１に記載の検査用プログラム生成装置。
【請求項３】
前記書き換え手段は、
前記拡張ポインタ構造体のポインタ値を書き換える命令記述を生成した場合、当該ポインタ値の書き換え操作に付随して前記検査値を更新することで、当該検査値が当該ポインタ値とその参照先メモリ領域に割り当てられた識別番号とを加算した値を示す状態を持続させる命令記述を追加する、
ことを特徴とする請求項１または請求項２の何れか１項に記載の検査用プログラム生成装置。
【請求項４】
前記書き換え手段は、
前記検査対象プログラムに含まれる、前記拡張ポインタ構造体を用いて算出した整数型変数を、前記拡張ポインタ構造体のポインタ値を用いて算出した値を示す整数値、及び前記拡張ポインタ構造体の検査値を用いて算出した値を示す検査値で構成される拡張整数型構造体に変換し、
当該変換により、前記拡張整数型構造体を用いて格調ポインタ構造体のポインタ値を算出する命令記述が生成された場合、当該ポインタ値の算出に関わる拡張整数型構造体の整数値と前記拡張ポインタ構造体のポインタ値とを、当該拡張整数型構造体の検査値と前記拡張ポインタ構造体の検査値とに置換してポインタ値を算出し、前記拡張ポインタ構造体の検査値に代入する命令記述を追加する、
ことを特徴とする請求項１から請求項３の何れか１項に記載の検査用プログラム生成装置。
【請求項５】
前記書き換え手段は、
前記検査対象プログラムに含まれる、ある拡張整数型構造体を用いて算出した整数型変数を他の拡張整数型構造体に変換し、
当該他の拡張整数型構造体の整数値に、前記ある拡張整数型構造体の整数値から算出された値を代入し、当該他の拡張整数型構造体の検査値に、前記ある拡張整数型構造体の検査値から算出された値を代入する命令記述を生成する、
ことを特徴とする請求項４に記載の検査用プログラム生成装置。
【請求項６】
前記書き換え手段は、
前記メモリ領域に割り当てる識別番号を、前記検査対象プログラムで用いられるメモリ領域に格納されるデータの型のサイズの整数倍の数とし、
前記拡張ポインタ構造体の検査値を、当該拡張ポインタ構造体のポインタ値に、当該ポインタ値の参照先メモリ領域に割り当てられた識別番号を当該メモリ領域に格納されるデータの型のサイズで除算した値を加算した値とし、
前記検査対象プログラムのうち、ポインタ変数を用いたメモリアクセスの命令記述の前に、前記拡張ポインタ構造体の検査値から前記ポインタ値を減じた値を算出し、前記メモリ領域テーブルの中から、当該値を前記拡張ポインタ構造体のポインタ値が示すデータの型のサイズで乗じた値と一致する識別番号のメモリ領域のアドレス範囲を取得し、アクセス先のアドレスが当該アドレス範囲に含まれるか否かを判定させる命令記述を追加する、
ことを特徴とする請求項１から請求項５の何れか１項に記載の検査用プログラム生成装置。
【請求項７】
検査対象プログラムから当該検査対象プログラムのメモリアクセスのアドレス範囲を検査する検査用プログラムを生成する検査用プログラム生成装置を用いた検査用プログラム生成方法であって、
書き換え手段は、
前記検査対象プログラムで用いられるメモリ領域の各々に対して識別番号を割り当てる命令記述を当該検査対象プログラムに追加し、
前記検査対象プログラムに含まれるポインタ変数を、当該ポインタ変数の参照先アドレスを示すポインタ値、及び当該ポインタ値と前記ポインタ変数の参照先メモリ領域に割り当てられた識別番号とを加算した値を示す検査値で構成される拡張ポインタ構造体に変換し、前記ポインタ変数に対してなされる命令記述を、前記拡張ポインタ構造体のポインタ値に対してなされる命令記述に変換し、
前記検査対象プログラムに含まれる、ポインタ変数を用いたメモリアクセスを行う命令記述の前に、前記拡張ポインタ構造体の検査値から前記ポインタ値を減じた値を算出させ、アクセス対象となるメモリ領域の識別番号が当該値と等しいメモリ領域の範囲に含まれるか否かを判定することで境界検査を行う命令記述を追加し、
出力手段は、前記書き換え手段によって命令記述の書き換えが行われた検査対象プログラムを検査用プログラムとして出力する、
ことを特徴とする検査用プログラム生成方法。
【請求項８】
検査対象プログラムから当該検査対象プログラムのメモリアクセスのアドレス範囲を検査する検査用プログラムを生成する検査用プログラム生成装置を、
前記検査対象プログラムで用いられるメモリ領域の各々に対して識別番号を割り当てる命令記述を当該検査対象プログラムに追加し、
前記検査対象プログラムに含まれるポインタ変数を、当該ポインタ変数の参照先アドレスを示すポインタ値、及び当該ポインタ値と前記ポインタ変数の参照先メモリ領域に割り当てられた識別番号とを加算した値を示す検査値で構成される拡張ポインタ構造体に変換し、前記ポインタ変数に対してなされる命令記述を、前記拡張ポインタ構造体のポインタ値に対してなされる命令記述に変換し、
前記検査対象プログラムに含まれる、ポインタ変数を用いたメモリアクセスを行う命令記述の前に、前記拡張ポインタ構造体の検査値から前記ポインタ値を減じた値を算出させ、アクセス対象となるメモリ領域の識別番号が当該値と等しいメモリ領域の範囲に含まれるか否かを判定することで境界検査を行う命令記述を追加する書き換え手段、
前記書き換え手段によって命令記述の書き換えが行われた検査対象プログラムを検査用プログラムとして出力する出力手段、
として動作させるプログラム。
【発明の詳細な説明】
【技術分野】
【０００１】
本発明は、検査対象プログラムによる不正なメモリアクセスを検出する検査用プログラムを生成する検査用プログラム生成装置、検査用プログラム生成方法及びプログラムに関する。
【背景技術】
【０００２】
ＰＣ（Personal Computer、パーソナルコンピュータ）、ワークステーション、組み込み装置等を動作させるコンピュータプログラムの開発する際のテストやデバッグの工程で行われるプログラムの検査として、メモリアクセスの境界検査（Boundary Test）がある。これは、コンピュータの実行部が実行するプログラムに従ってメモリにアクセスする際に、実行部がアクセスを行うメモリの参照アドレスが、プログラムの実行用に割り当てられたメモリ領域を示しているか否かを判定する検査である。例えば、アドレスの値を記憶するポインタ変数が使用できるＣ言語等を用いると、任意のメモリ領域を参照することができるため、実行部がプログラムの実行用に割り当てられていないメモリ領域の値へのアクセスを行ってしまう可能性がある。
実行部がプログラムの実行用に割り当てられていないメモリ領域の値へのアクセスを行うと、当該メモリ領域に格納されている他のデータを書き換えてしまう可能性がある。これによって、例えば当該プログラムまたは他のプログラムの動作が不安定になり、または、当該プログラムを実行する装置やシステムに重大な問題を生じさせる虞がある。
【０００３】
境界検査の手法として、検査対象のプログラムに基づいて検査用プログラムを生成し、当該検査用プログラムを実行することで不正メモリアクセスを検出する手法がある。検査用プログラムを生成することで境界検査を行う手法として、ポインタ変数が保持する情報量を増加させた拡張ポインタ構造体に、参照先のアドレスのみでなく、参照するメモリ領域の範囲を示す情報を持たせることで不正メモリアクセスを検出する手法が考案されている（例えば、非特許文献１を参照）。
【０００４】
ここで、検査用プログラム生成装置がプログラムの検査用プログラムを生成する例に説明する。
図１５は、従来のプログラム生成装置の動作説明に用いる検査対象プログラムを示す第１のプログラムリストである。
図１５に示すプログラムには、ｃｈａｒ型変数へのポインタｐを引数として受け取り、ポインタｐで指定されたアドレスのｃｈａｒ変数に値１を書き込ませる関数ｆ１が記述されている。また、ａｒｒａｙ１に１６バイトのメモリ領域を割り当て、ａｒｒａｙ２に８バイトのメモリ領域を割り当てている。さらに、メイン関数において、ａｒｒａｙ１＋８、ａｒｒａｙ２＋８を引数に関数ｆ１を呼び出している。このとき、前者の呼び出しは、ａｒｒａｙ１の正常範囲に値を書き込む正しい記述であり、後者の呼び出しは、ａｒｒａｙ２の範囲を逸脱した不正な記述である。
【０００５】
図１６は、従来のプログラム生成装置が生成する検査用プログラムを示す第１のプログラムリストである。
検査用プログラム生成装置は、これらのメモリアクセスに対して正常であるか不正であるかを正しく判定するために、図１６に示すように、拡張ポインタを用いる検査用プログラムを生成する。検査用プログラム生成装置は、ポインタ型の変数を、当該ポインタ変数が本来保持している参照先アドレスに加え、参照先のメモリ領域の識別子を記憶させる領域を設けたｆａｔｐｔｒ＿ｃｈａｒ構造体に置換する。ｆａｔｐｔｒ＿ｃｈａｒ構造体は、参照先のアドレスを格納するｖａｌと参照するメモリ領域の先頭アドレスを格納するｂａｓｅの２つのポインタ変数を持つ。そして、関数ｆ１で＿＿ｒａｎｇｅ＿ｃｈｅｃｋ関数を実行することで、境界検査を行う。ここで、＿＿ｒａｎｇｅ＿ｃｈｅｃｋ関数は、ｆａｔｐｔｒ＿ｃｈａｒ構造体のｂａｓｅ変数に基づいて参照するメモリ領域に割り当てられた範囲を算出し、ｖａｌ変数が当該範囲内を示しているか否かを判定する関数である。
このように、ポインタ型を、参照先のアドレスと参照先メモリ領域の先頭アドレスとを格納する拡張ポインタに書き換えることで、不正なメモリアクセスの検出を行うことができる。
【先行技術文献】
【非特許文献】
【０００６】
【非特許文献１】Todd M. Austin、Scott E. Breach、Gurindar S. Sohi、「Efficient Detection of All Pointer and Array Access Errors」、ACM SIGPLAN Notices、（米国）、１９９４年６月、第２９巻、第６号、ｐ．２９０−３０１
【発明の概要】
【発明が解決しようとする課題】
【０００７】
しかしながら、従来の拡張ポインタ構造体を用いた検査用プログラムは、ポインタ変数が示すアドレス値を用いた演算を含むプログラムに対し、誤ったエラー情報を出力する可能性が有るという問題がある。
以下に、従来の拡張ポインタ構造体を用いた境界検査で正しく検査を行うことができないプログラムの例を示す。
図１７は、従来のプログラム生成装置の動作説明に用いる検査対象プログラムを示す第２のプログラムリストである。
検査対象プログラムには、ｃｈａｒ型変数へのポインタｐを引数として受け取り、ポインタｐで指定されたアドレスのｃｈａｒ変数に値１を書き込ませる関数ｆ１が記述されている。また、ａｒｒａｙ１に１６バイトのメモリ領域を割り当て、ａｒｒａｙ２に８バイトのメモリ領域を割り当てている。さらに、メイン関数において、ポインタ変数ｐ１にａｒｒａｙ１の先頭アドレスを格納させ、ポインタ変数ｐ２にａｒｒａｙ２の先頭アドレスを格納させている。次に、整数ｄとして、ポインタ変数ｐ１とｐ２とのアドレス差を算出し、得られた整数ｄに２を加算した値をオフセットとしてポインタ変数ｐ１に加算した後、当該ｐ１を引数に関数ｆ１を呼び出している。
【０００８】
検査用プログラム生成装置は図１７に示す検査対象プログラムを実行すると、ａｒｒａｙ１の先頭アドレスにａｒｒａｙ１とａｒｒａｙ２のアドレス差に２を加算したポインタ、すなわちａｒｒａｙ２の先頭アドレス＋２の位置に、値を書き込む動作を行う。つまり、メイン関数を実行することで行われるアクセスは、常にａｒｒａｙ２へのアクセスとなり、メイン関数に記述された命令は、正常な動作を行う命令記述となっている。
【０００９】
図１８は、従来のプログラム生成装置が生成する検査用プログラムを示す第２のプログラムリストである。
ここで、実行装置が生成された検査用プログラムを実行すると、関数ｆ１内において、ｆａｔｐｔｒ＿ｃｈａｒ構造体ｐのｂａｓｅ変数は、ａｒｒａｙ１を示すため、実行装置は、メイン関数を実行することでなされるアクセスがａｒｒａｙ１へのアクセスであると判定する。そのため、実行装置は、当該アクセスがａｒｒａｙ１の範囲外へのアクセスであると判定し、当該アクセスが不正メモリアクセスであることを示すエラー情報を出力することとなる。すなわち、従来の拡張ポインタ構造体による検査用プログラムの生成手法で第２のプログラムリストを検査するとエラーとして判定する。
【００１０】
Ｃ言語の規格では、２つのポインタｐ１、ｐ２の差を得る計算式「ｐ２−ｐ１」を評価する際、ポインタｐ２とｐ１とが参照するメモリ領域が同じでなくてはならないという規則が定められている。しかし、図１８に示す第２のプログラムリストでは、「ｐ２−ｐ１」によって得られる値がポインタｐ２とｐ１の参照先アドレスの差であるという保証はない。そのため、第２のプログラムリストに示すプログラムは、Ｃ言語の規格から逸脱したプログラムであり、従来の拡張ポインタ構造体による検査用プログラムの生成手法がこのプログラムをエラーであると判定する動作は妥当である。
【００１１】
しかしながら、Ｃ言語の規格では規定されていないが、実在する多数のＣ言語プログラム処理系では、ｃｈａｒポインタ変数の差「ｐ２−ｐ１」を計算すると、ポインタｐ２とｐ１の参照先アドレス差を得ることができる。そのため、このような動作を行うＣ言語処理系であることを前提に記述されたプログラムが多数存在し、使用されている。これらのプログラムに記述されたメモリアクセスのアドレス範囲について境界検査を行いたい場合、上述した従来の拡張ポインタ構造体による検査プログラム手法を適用することができないという問題がある。
その際、従来の拡張ポインタ構造体による検査用プログラムの生成手法は、上述したような問題を解決する機能の拡張ができないという問題があった。
【００１２】
本発明は上記の点に鑑みてなされたものであり、その目的は、メモリアクセス先のアドレスを任意の整数演算により算出する処理を含むプログラムに対しても境界検査を実施することができるように機能を拡張することができる検査用プログラムを生成する検査用プログラム生成装置、検査用プログラム生成方法及びプログラムを提供することにある。
【課題を解決するための手段】
【００１３】
本発明は上記の課題を解決するためになされたものであり、検査対象プログラムから当該検査対象プログラムのメモリアクセスのアドレス範囲を検査する検査用プログラムを生成する検査用プログラム生成装置であって、前記検査対象プログラムで用いられるメモリ領域の各々に対して識別番号を割り当てる命令記述を当該検査対象プログラムに追加し、前記検査対象プログラムに含まれるポインタ変数を、当該ポインタ変数の参照先アドレスを示すポインタ値、及び当該ポインタ値と前記ポインタ変数の参照先メモリ領域に割り当てられた識別番号とを加算した値を示す検査値で構成される拡張ポインタ構造体に変換し、前記ポインタ変数に対してなされる命令記述を、前記拡張ポインタ構造体のポインタ値に対してなされる命令記述に変換し、前記検査対象プログラムに含まれる、ポインタ変数を用いたメモリアクセスを行う命令記述の前に、前記拡張ポインタ構造体の検査値から前記ポインタ値を減じた値を算出させ、アクセス対象となるメモリ領域の識別番号が当該値と等しいメモリ領域の範囲に含まれるか否かを判定することで境界検査を行う命令記述を追加する書き換え手段と、前記書き換え手段によって命令記述の書き換えが行われた検査対象プログラムを検査用プログラムとして出力する出力手段と、を備えることを特徴とする。
【００１４】
また、本発明は、検査対象プログラムから当該検査対象プログラムのメモリアクセスのアドレス範囲を検査する検査用プログラムを生成する検査用プログラム生成装置を用いた検査用プログラム生成方法であって、書き換え手段は、前記検査対象プログラムで用いられるメモリ領域の各々に対して識別番号を割り当てる命令記述を当該検査対象プログラムに追加し、前記検査対象プログラムに含まれるポインタ変数を、当該ポインタ変数の参照先アドレスを示すポインタ値、及び当該ポインタ値と前記ポインタ変数の参照先メモリ領域に割り当てられた識別番号とを加算した値を示す検査値で構成される拡張ポインタ構造体に変換し、前記ポインタ変数に対してなされる命令記述を、前記拡張ポインタ構造体のポインタ値に対してなされる命令記述に変換し、前記検査対象プログラムに含まれる、ポインタ変数を用いたメモリアクセスを行う命令記述の前に、前記拡張ポインタ構造体の検査値から前記ポインタ値を減じた値を算出させ、アクセス対象となるメモリ領域の識別番号が当該値と等しいメモリ領域の範囲に含まれるか否かを判定することで境界検査を行う命令記述を追加し、出力手段は、前記書き換え手段によって命令記述の書き換えが行われた検査対象プログラムを検査用プログラムとして出力する、ことを特徴とする。
【００１５】
また、本発明は、検査対象プログラムから当該検査対象プログラムのメモリアクセスのアドレス範囲を検査する検査用プログラムを生成する検査用プログラム生成装置を、前記検査対象プログラムで用いられるメモリ領域の各々に対して識別番号を割り当てる命令記述を当該検査対象プログラムに追加し、前記検査対象プログラムに含まれるポインタ変数を、当該ポインタ変数の参照先アドレスを示すポインタ値、及び当該ポインタ値と前記ポインタ変数の参照先メモリ領域に割り当てられた識別番号とを加算した値を示す検査値で構成される拡張ポインタ構造体に変換し、前記ポインタ変数に対してなされる命令記述を、前記拡張ポインタ構造体のポインタ値に対してなされる命令記述に変換し、前記検査対象プログラムに含まれる、ポインタ変数を用いたメモリアクセスを行う命令記述の前に、前記拡張ポインタ構造体の検査値から前記ポインタ値を減じた値を算出させ、アクセス対象となるメモリ領域の識別番号が当該値と等しいメモリ領域の範囲に含まれるか否かを判定することで境界検査を行う命令記述を追加する書き換え手段、前記書き換え手段によって命令記述の書き換えが行われた検査対象プログラムを検査用プログラムとして出力する出力手段、として動作させるプログラムである。
【発明の効果】
【００１６】
本発明によれば、検査用プログラム生成装置によって検査用プログラムに記述される拡張ポインタ構造体は、ポインタ変数が示すアドレスを指すポインタ値と、ポインタ変数が示すアドレスに先頭アドレスを示す識別番号を加算した検査値とを格納する。そして、検査値からポインタ値を減じることで、アクセス対象となるメモリ領域の識別番号を取得する。これにより、アクセスの範囲が取得した識別番号のメモリ領域以内に収まっているか否かを判定することで、従来の拡張ポインタ構造体を用いた検査用プログラムと同様に不正メモリアクセスチェックを行うことができる。
【００１７】
さらに、拡張ポインタ構造体を用いて算出した整数型変数を、拡張ポインタ構造体のポインタ値を用いて算出した値を示す整数値、及び前記拡張ポインタ構造体の検査値を用いて算出した値を示す検査値で構成される拡張整数型構造体に変換し、当該変換した拡張整数型構造体を用いて算出した整数型変数を前記拡張整数型構造体に変換するように機能を拡張することで、メモリアクセス先のアドレスを任意の整数演算により算出する処理を含むプログラムに対しても境界検査を実施することができる。
【図面の簡単な説明】
【００１８】
【図１】本発明の第１の実施形態による検査用プログラム生成装置の構成を示す概略ブロック図である。
【図２】検査用プログラム生成装置の動作を示す第１のフローチャートである。
【図３】第１の検査対象プログラムを示すプログラムリストである。
【図４】検査用プログラム生成装置が生成する第１の検査用プログラムを示すプログラムリストである。
【図５】検査用プログラム生成装置の動作を示す第２のフローチャートである。
【図６】第２の検査対象プログラムを示すプログラムリストである。
【図７】検査用プログラム生成装置が生成する第２の検査用プログラムを示すプログラムリストである。
【図８】第３の検査対象プログラムを示すプログラムリストである。
【図９】検査用プログラム生成装置が生成する第３の検査用プログラムを示すプログラムリストである。
【図１０】検査用プログラム生成装置の動作を示す第３のフローチャートである。
【図１１】第４の検査対象プログラムを示すプログラムリストである。
【図１２】検査用プログラム生成装置が生成する第４の検査用プログラムを示すプログラムリストである。
【図１３】第５の検査対象プログラムを示すプログラムリストである。
【図１４】検査用プログラム生成装置が生成する第５の検査用プログラムを示すプログラムリストである。
【図１５】従来のプログラム生成装置の動作説明に用いる検査対象プログラムを示す第１のプログラムリストである。
【図１６】従来のプログラム生成装置が生成する検査用プログラムを示す第１のプログラムリストである。
【図１７】従来のプログラム生成装置の動作説明に用いる検査対象プログラムを示す第２のプログラムリストである。
【図１８】従来のプログラム生成装置が生成する検査用プログラムを示す第２のプログラムリストである。
【発明を実施するための形態】
【実施例１】
【００１９】
以下、図面を参照しながら本発明の第１の実施形態について詳しく説明する。
図１は、本発明の第１の実施形態による検査用プログラム生成装置の構成を示す概略ブロック図である。
検査用プログラム生成装置は、入力部１、プログラム記憶部２、解釈部３、書き換え部４（書き換え手段）、出力部５（出力手段）を備える。
入力部１は、記憶媒体が記憶する情報の読み取りや他の装置からの通信、または手入力による検査対象プログラムの入力を受け付ける。
プログラム記憶部２は、入力部１が入力を受け付けた検査対象プログラムを記憶する。
解釈部３は、プログラム記憶部２が記憶する検査対象プログラムを逐次解釈し、プログラム書き換え部４に解釈結果を出力する。
書き換え部４は、プログラム記憶部２が記憶する検査対象プログラムを検査用プログラムに書き換える。
出力部５は、プログラム書き換え部４が書き換えを行った検査用プログラムを出力する。
【００２０】
そして、検査用プログラム生成装置において、書き換え部４は、検査対象プログラムで用いられるメモリ領域の各々に対して識別番号を割り当てさせる命令記述を追加し、検査対象プログラムに含まれるポインタ変数を、当該ポインタ変数の参照先アドレスを示すポインタ値、及び当該ポインタ値とポインタ変数の参照先メモリ領域に割り当てられた識別番号とを加算した値を示す検査値で構成される拡張ポインタ構造体に変換する。次に、書き換え部４は、ポインタ変数に対してなされる命令記述を、拡張ポインタ構造体のポインタ値に対してなされる命令記述に変換する。
次に、書き換え部４は、検査対象プログラムに含まれる、ポインタ変数を用いたメモリアクセスの命令記述の前に、拡張ポインタ構造体の検査値からポインタ値を減じた値を算出させ、アクセス対象となるメモリ領域の識別番号が当該値と等しいメモリ領域の範囲に含まれるか否かを判定させる命令記述を追加する。
次に、出力部５は、書き換え部４によって命令記述の書き換えが行われた検査対象プログラムを検査用プログラムとして出力する。
これにより、従来の拡張ポインタ構造体を用いた検査用プログラム生成方法と同等の境界検査を実施することができ、さらに、メモリアクセス先のアドレスを任意の整数演算により算出する処理を含むプログラムに対しても境界検査を実施することができるように機能を拡張することができる。
【００２１】
次に、フローチャート及び具体的な例を示すプログラムリストを用いて本発明の第１の実施形態による検査用プログラム生成装置の動作を説明する。
図２は、検査用プログラム生成装置の動作を示す第１のフローチャートである。
図３は、第１の検査対象プログラムを示すプログラムリストである。
図４は、検査用プログラム生成装置が生成する第１の検査用プログラムを示すプログラムリストである。
まず、第１の検査対象プログラムについて説明する。
図３に示す第１の検査対象プログラムは、ｃｈａｒ型変数へのポインタｐを引数として受け取り、ポインタｐで指定されたアドレスのｃｈａｒ変数に値１を書き込ませる命令１１１を実行する関数１１０が記述されている。また、ａｒｒａｙ１に１６バイトのメモリ領域を割り当て、ａｒｒａｙ２に８バイトのメモリ領域を割り当てる宣言１２０が記述されている。また、メイン関数１３０には、命令１３１、命令１３２が記述されている。
命令１３１は、ａｒｒａｙ１＋８を引数に関数１１０を呼び出す命令である。
命令１３２は、ａｒｒａｙ２＋８を引数に関数１１０を呼び出す命令である。
このとき、命令１３１は、ａｒｒａｙ１の正常範囲に値を書き込む正しい記述であり、命令１３２は、ａｒｒａｙ２の範囲を逸脱した不正な記述である。
【００２２】
なお、本実施形態で示す検査対象プログラム及び検査用プログラムのプログラムリストは、Ｃ言語によって記述されているが、これに限られず、ポインタ変数を扱うことができる他のプログラミング言語を用いても良い。
また、生成された検査用プログラムの記述言語が検査対象プログラムと同一である必要は無く、例えば、Ｃ言語の検査対象プログラムからＣ＋＋言語プログラムに変換しても良い。もしくは、Ｃ言語プログラムからＣＰＵ用の機械語命令プログラムを生成するコンパイラと組み合わせることで、検査機能を有する機械語命令プログラムを直接生成しても良い。
【００２３】
次に、検査用プログラム生成装置の動作を説明する。
まず、利用者が、検査対象プログラムを格納した記憶媒体を検査用プログラム生成装置の挿入口に挿入するなどして検査用プログラム生成装置に検査対象プログラムの入力を行うと、入力部１１は、検査対象プログラムの入力を受け付け、当該検査対象プログラムをプログラム記憶部１２に登録する（ステップＳ１）。
【００２４】
入力部１がプログラム記憶部２に検査対象プログラムを登録すると、書き換え部４は、プログラム記憶部２が記憶する検査対象プログラムに、メモリ領域の管理を行う関数及び変数を格納したモジュールを追加する（ステップＳ２）。追加するモジュールには、検査対象プログラムが実行中に使用するメモリ領域に識別番号を付与し、開始アドレス、サイズをメモリ領域テーブルに登録及び削除する関数、メモリ領域テーブルからメモリ領域の識別番号を取得する関数、及び境界検査を実行する関数を記述する。具体的には、図４の命令１３３に記述されている＿＿ｒｅｇｉｓｔｅｒ関数、命令１３６に記述されている＿＿ｕｎｒｅｇｉｓｔｅｒ関数、命令１３４、１３５に記述されている＿＿ｓｅｇ＿ｉｄ関数、命令１１２に記述されている＿＿ｒａｎｇｅ＿ｃｈｅｃｋ関数が追加するモジュールに記述されている。
【００２５】
ここで、追加するモジュールに記述されている関数の各々の詳細を説明する。
＿＿ｒｅｇｉｓｔｅｒ関数は、引数として変数名と当該変数のサイズとを受け取る。引数を受け取ると、受け取った変数名が示すメモリ領域に対し、メモリ領域テーブルに登録されていない識別番号を付与する。＿＿ｒｅｇｉｓｔｅｒ関数は、識別番号を付与すると、メモリ領域テーブルに、付与した識別番号に紐づけて、メモリ領域の先頭アドレスと、当該メモリ領域のサイズとを登録する。
＿＿ｕｎｒｅｇｉｓｔｅｒ関数は、引数として変数名を受け取る。引数を受け取ると、メモリ領域テーブルから、受け取った変数名が示すメモリ領域に紐づけられた情報を削除する。
＿＿ｓｅｇ＿ｉｄ関数は、引数として変数名を受け取る。引数を受け取ると、メモリ領域テーブルから、受け取った変数名が示すメモリ領域の識別番号を取得する。
＿＿ｒａｎｇｅ＿ｃｈｅｃｋ関数は、引数として拡張ポインタ構造体のポインタ値と、検査値とポインタ値との差とを受け取る。引数を受け取ると、受け取った検査値とポインタ値との差と等しい値の識別番号がメモリ領域テーブルに格納されているか否かを判定し、格納されている場合は、受け取ったポインタ値が当該識別番号に紐づけられたメモリ領域のサイズ内に収まっているか否かを判定する。ポインタ値がメモリ領域のサイズ内に収まっていると判定された場合に、当該メモリアクセス命令が正しい記述であると判定する。
【００２６】
ステップＳ２で書き換え部４が関数及び変数の記述を追加すると、解釈部３は、プログラム記憶部２が記憶する検査対象プログラムを逐次解釈し、検査対象プログラムのうち、メモリ領域を確保する命令が記述されている位置を取得する（ステップＳ３）。メモリ領域を確保する命令とは、例えば、Ｃ言語の場合、グローバル変数の宣言、関数などのブロック内の自動変数の宣言、ｍａｌｌｏｃ関数の呼び出しによるヒープメモリ領域の確保処理がある。次に、書き換え部４は、プログラム記憶部２が記憶する検査対象プログラムのうち、解釈部３が取得した位置に記載されているメモリ領域を確保する命令の次に、当該メモリ領域に識別番号を付与し、メモリ領域テーブルに当該メモリ領域の情報を登録する＿＿ｒｅｇｉｓｔｅｒ関数を追加する（ステップＳ４）。具体的には、図４に示す命令１３３を検査対象プログラムに追加する。なお、ここでは、宣言１２０によってａｒｒａｙ１、ａｒｒａｙ２がグローバル変数として定義されているので、＿＿ｒｅｇｉｓｔｅｒ関数はメイン関数１３０の先頭に追加されている。
【００２７】
ステップＳ４で書き換え部４が＿＿ｒｅｇｉｓｔｅｒ関数を追加すると、解釈部３は、プログラム記憶部２が記憶する検査対象プログラムを逐次解釈し、検査対象プログラムのうち、メモリ領域を解放する命令が記述されている位置を取得する（ステップＳ５）。メモリ領域を解放する命令とは、例えば、Ｃ言語の場合、関数などのブロックから脱出する際の自動変数の解放や、ｆｒｅｅ関数の呼び出しがある。次に、書き換え部４は、プログラム記憶部２が記憶する検査対象プログラムのうち、解釈部３が取得した位置に記載されているメモリ領域を解放する命令の前に、当該メモリ領域の情報をメモリ領域テーブルから削除する＿＿ｕｎｒｅｇｉｓｔｅｒ関数を追加する（ステップＳ６）。具体的には、図４に示す命令１３６を検査対象プログラムに追加する。なお、ここでは、メイン関数１３０を脱出することでａｒｒａｙ１、ａｒｒａｙ２が解放されるので、＿＿ｕｎｒｅｇｉｓｔｅｒ関数はメイン関数１３０の末尾に追加されている。
【００２８】
ステップＳ６で書き換え部４が＿＿ｕｎｒｅｇｉｓｔｅｒ関数を追加すると、解釈部３は、プログラム記憶部２が記憶する検査対象プログラムを逐次解釈し、検査対象プログラムで用いられているポインタ変数が指すアドレスに格納されるデータの型を取得する（ステップＳ７）。例えば、図３に示す検査対象プログラムの場合、関数１１０で用いられているポインタ変数ｐは、「ｃｈａｒ  ＊ｐ」と記載されているため、ｃｈａｒ型のデータを格納するアドレスを指している。
【００２９】
ステップＳ７で解釈部３がデータの型を取得すると、書き換え部４は、プログラム記憶部２が記憶する検査対象プログラムに、取得した型のポインタ変数ｍａｉｎ（ポインタ値）及びｓｕｂ（検査値）を格納する拡張ポインタ構造体の宣言を追加する（ステップＳ８）。具体的には、図４に示す宣言１４０を検査対象プログラムに追加する。なお、ここでは、図３に示す検査対象プログラムでｃｈａｒ型のポインタ変数ｐが用いられているので、ｃｈａｒ型のポインタ変数ｍａｉｎ、ｓｕｂを格納し、ｃｈａｒ型のポインタ変数に対応する拡張ポインタ構造体であるｄｕａｌｐｔｒ＿ｃｈａｒ構造体を宣言している。
【００３０】
ステップＳ８で書き換え部４が拡張ポインタ構造体の宣言を追加すると、解釈部３は、プログラム記憶部２が記憶する検査対象プログラムを逐次解釈し、検査対象プログラムのうち、ポインタ変数を用いた処理が記述されている位置を取得する（ステップＳ９）。ポインタ変数を用いた処理とは、例えば、ポインタ変数への値の代入、ポインタ変数や配列変数によるメモリアクセスがある。
【００３１】
次に、書き換え部４は、プログラム記憶部２が記憶する検査対象プログラムのうち、解釈部３が取得した位置に記載されているポインタ変数を用いた処理を行う命令を、ステップＳ８で宣言を追加した拡張ポインタ構造体を用いた処理に書き換える（ステップＳ１０）。
このとき、拡張ポインタ構造体の変数ｍａｉｎに、書き換え前のポインタ変数が示す値を格納する。また、拡張ポインタ構造体の変数ｓｕｂには、変数ｍａｉｎが格納する値にアクセス対象となるメモリ領域の識別番号を加算した値を格納する。このとき、アクセス対象となるメモリ領域の識別番号は、上述した＿＿ｓｅｇ＿ｉｄ関数によってメモリ領域テーブルから取得することができる。
また、ポインタ変数に対する演算は、全て拡張ポインタ型構造体の変数ｍａｉｎに対する演算として書き換える。このとき、変数ｍａｉｎの値が変更された場合は、変数ｓｕｂと変数ｍａｉｎとの差がアクセス対象となるメモリ領域の識別番号となるように命令を追加する。
書き換え部４の処理は、具体的には、図３に示す命令１１１、１３１、１３２をそれぞれ図４に示す命令１１３、１３４、１３５に書き換える処理である。
【００３２】
ステップＳ１０で書き換え部４がポインタ変数を拡張ポインタ構造体に書き換えると、解釈部３は、プログラム記憶部２が記憶する検査対象プログラムを逐次解釈し、検査対象プログラムのうち、拡張ポインタ構造体を用いたメモリアクセス命令が記述されている位置を取得する（ステップＳ１１）。次に、書き換え部４は、プログラム記憶部２が記憶する検査対象プログラムのうち、解釈部３が取得した位置に記載されている拡張ポインタ型構造体によるメモリアクセス命令の前に、当該メモリアクセスの境界検査を行う＿＿ｒａｎｇｅ＿ｃｈｅｃｋ関数を追加する（ステップＳ１２）。具体的には、図４に示す命令１１２を検査対象プログラムに追加する。
【００３３】
上述したように、＿＿ｒａｎｇｅ＿ｃｈｅｃｋ関数は、引数として拡張ポインタ構造体のポインタ値と、検査値とポインタ値との差とを受け取る。引数を受け取ると、受け取った変数ｓｕｂと変数ｍａｉｎとの差と等しい値の識別番号がメモリ領域テーブルに格納されているか否かを判定し、格納されている場合は、受け取ったポインタ値が当該識別番号に紐づけられたメモリ領域のサイズ内に収まっているか否かを判定する。ポインタ値がメモリ領域のサイズ内に収まっていると判定された場合に、当該メモリアクセス命令が正しい記述であると判定する。
【００３４】
ステップＳ１２で書き換え部４が＿＿ｒａｎｇｅ＿ｃｈｅｃｋ関数を追加すると、出力部５は、プログラム記憶部２が記憶する検査対象プログラムを検査用プログラムとして出力する（ステップＳ１３）。
【００３５】
次に、上述した動作によって生成された第１の検査用プログラムを実行することで境界検査が実行できることを説明する。
実行装置が図４に示す第１の検査用プログラムを実行すると、まず、メイン関数１３０の命令１３３を実行する。これにより、ａｒｒａｙ１、ａｒｒａｙ２に識別番号が割り振られ、それぞれのアドレス範囲がメモリ領域テーブルに登録される。
次に、実行装置は命令１３４を実行する。これにより、拡張ポインタ構造体ｐが生成され、拡張ポインタ構造体ｐの変数ｍａｉｎに変数ａｒｒａｙ１の先頭アドレス＋８の値が格納され、変数ｓｕｂに変数ｍａｉｎと変数ａｒｒａｙ１が示すメモリ領域に割り当てられた識別番号とを加算した値が格納される。この処理は、図３に示す命令１３１に相当する。
【００３６】
次に、実行装置は、拡張ポインタ構造体ｐを引数として関数１１０を呼び出す。
関数１１０が呼び出されると、実行装置は、命令１１２を実行する。これにより、実行装置は、まず拡張ポインタ構造体ｐの変数ｓｕｂと変数ｍａｉｎとの差と等しい値の識別番号がメモリ領域テーブルに格納されているか否かを判定する。変数ｓｕｂと変数ｍａｉｎとの差は、変数ａｒｒａｙ１のメモリ領域に識別番号と等しいため、実行装置は、次に、受け取ったポインタ値が当該識別番号に紐づけられたメモリ領域のサイズ内に収まっているか否かを判定する。変数ｍａｉｎに格納されているアドレスは、変数ａｒｒａｙ１の先頭アドレス＋８であり、変数ａｒｒａｙ１のサイズは１６であるため、実行装置は、ポインタ値がメモリ領域のサイズ内に収まっていると判定する。従って、当該メモリアクセス命令が正しい記述であると判定する。
次に、実行装置は、命令１１３を実行する。これにより、実行装置は、図３に示す命令１１１と等価の動作を行う。
【００３７】
次に、実行装置は命令１３５を実行する。これにより、拡張ポインタ構造体ｐの変数ｍａｉｎに変数ａｒｒａｙ２の先頭アドレス＋８の値が格納され、変数ｓｕｂに変数ｍａｉｎと変数ａｒｒａｙ２の識別番号とを加算した値が格納される。この処理は、図３に示す命令１３２に相当する。
【００３８】
次に、実行装置は、拡張ポインタ構造体ｐを引数として関数１１０を呼び出す。
関数１１０が呼び出されると、実行装置は、命令１１２を実行する。これにより、実行装置は、まず拡張ポインタ構造体ｐの変数ｓｕｂと変数ｍａｉｎとの差と等しい値の識別番号がメモリ領域テーブルに格納されているか否かを判定する。変数ｓｕｂと変数ｍａｉｎとの差は、変数ａｒｒａｙ２のメモリ領域に識別番号と等しいため、実行装置は、次に、受け取ったポインタ値が当該識別番号に紐づけられたメモリ領域のサイズ内に収まっているか否かを判定する。変数ｍａｉｎに格納されているアドレスは、変数ａｒｒａｙ２の先頭アドレス＋８であり、変数ａｒｒａｙ２のサイズは８であるため、実行装置は、ポインタ値がメモリ領域のサイズ内に収まっていないと判定する。従って、当該メモリアクセス命令が不正な記述であると判定する。
次に、実行装置は、命令１１３を実行する。これにより、実行装置は、図３に示す命令１１１と等価の動作を行う。なお、実行装置は、＿＿ｒａｎｇｅ＿ｃｈｅｃｋ関数によって不正な記述であると判定したときに例外処理を行って強制的に処理を終了しても良い。
【００３９】
このように、本実施形態によれば、検査用プログラム生成装置によって生成される検査用プログラムに記述される拡張ポインタ構造体は、ポインタ変数が示すアドレスを指す変数ｍａｉｎと、ポインタ変数が示すアドレスに先頭アドレスを示す識別番号を加算した変数ｓｕｂとを格納する。そして、変数ｓｕｂから変数ｍａｉｎを減じることで、アクセス対象となるメモリ領域の識別番号を取得する。これにより、アクセスの範囲が取得した識別番号のメモリ領域以内に収まっているか否かを判定することで、従来の拡張ポインタ構造体を用いた検査用プログラムと同様に不正メモリアクセスチェックを行うことができる。
【実施例２】
【００４０】
次に、本発明の第２の実施形態について詳しく説明する。
第２の実施形態では、第１の実施形態による検査用プログラム生成装置を拡張し、メモリアクセス先のアドレスを任意の整数演算により算出する処理を含むプログラムに対しても境界検査を実施することができるようにしたものについて説明する。
第２の実施形態による検査用プログラム生成装置は、第１の実施形態による検査用プログラム生成装置と同じ構成とし、書き換え部４が、プログラム記憶部２が記憶する検査対象プログラムに含まれる、拡張ポインタ構造体を用いて算出した整数型変数を、拡張ポインタ構造体のポインタ値に相当する整数値、及び拡張ポインタ構造体の検査値に相当する検査値で構成される拡張整数型構造体に変換し、さらに、拡張整数型構造体を用いて算出した整数型変数を拡張整数型構造体に変換することを特徴とする。
【００４１】
次に、フローチャート及び具体的な例を示すプログラムリストを用いて本発明の第２の実施形態による検査用プログラム生成装置の動作を説明する。
図５は、検査用プログラム生成装置の動作を示す第２のフローチャートである。
図６は、第２の検査対象プログラムを示すプログラムリストである。
図７は、検査用プログラム生成装置が生成する第２の検査用プログラムを示すプログラムリストである。
まず、第２の検査対象プログラムについて説明する。
図６に示す第２の検査対象プログラムは、ｃｈａｒ型変数へのポインタｐを引数として受け取り、ポインタｐで指定されたアドレスのｃｈａｒ変数に値１を書き込ませる命令２１１を実行する関数２１０が記述されている。また、ａｒｒａｙ１に１６バイトのメモリ領域を割り当て、ａｒｒａｙ２に８バイトのメモリ領域を割り当てる宣言２２０が記述されている。また、メイン関数２３０には、命令２３１、命令２３２、命令２３３が記述されている。
命令２３１は、ポインタ変数ｐ１にａｒｒａｙ１の先頭アドレスを格納し、ポインタ変数ｐ２にａｒｒａｙ２の先頭アドレスを格納する命令である。
命令２３２は、整数ｄとして、ポインタ変数ｐ１とｐ２とのアドレス差を算出し、得られた整数ｄに２を加算した値をオフセットとしてポインタ変数ｐ１に加算する命令である。
命令２３３は、ポインタ変数ｐ１を引数に関数２１０を呼び出す命令である。
【００４２】
実行装置が図６に示す第２の検査対象プログラムを実行すると、ａｒｒａｙ１の先頭アドレスにａｒｒａｙ１とａｒｒａｙ２のアドレス差に２を加算したポインタ、すなわちａｒｒａｙ２の先頭アドレス＋２の位置に、値を書き込む動作を行う。つまり、メイン関数２３０を実行することで行われるアクセスは、常にａｒｒａｙ２へのアクセスとなり、メイン関数２３０に記述された命令２３３は、正常な動作を行う命令記述となっている。
【００４３】
次に、検査用プログラム生成装置の動作を説明する。
まず、利用者が、検査対象プログラムを格納した記憶媒体を検査用プログラム生成装置の挿入口に挿入するなどして検査用プログラム生成装置に検査対象プログラムの入力を行うと、入力部１１は、検査対象プログラムの入力を受け付け、当該検査対象プログラムをプログラム記憶部１２に登録する（ステップＳ２１）。
【００４４】
入力部１がプログラム記憶部２に検査対象プログラムを登録すると、書き換え部４は、プログラム記憶部２が記憶する検査対象プログラムに、メモリ領域の管理を行う関数及び変数を格納したモジュールを追加する（ステップＳ２２）。第１の実施形態と同様に、追加するモジュールには、図７の命令２３４に記述されている＿＿ｒｅｇｉｓｔｅｒ関数、命令２３７に記述されている＿＿ｕｎｒｅｇｉｓｔｅｒ関数、命令２１２に記述されている＿＿ｓｅｇ＿ｉｄ関数、及び＿＿ｒａｎｇｅ＿ｃｈｅｃｋ関数が記述されている。
【００４５】
ステップＳ２２で書き換え部４が関数及び変数の記述を追加すると、解釈部３は、プログラム記憶部２が記憶する検査対象プログラムを逐次解釈し、検査対象プログラムのうち、メモリ領域を確保する命令が記述されている位置を取得する（ステップＳ２３）。次に、書き換え部４は、プログラム記憶部２が記憶する検査対象プログラムのうち、解釈部３が取得した位置に記載されているメモリ領域を確保する命令の次に、当該メモリ領域に識別番号を付与し、メモリ領域テーブルに当該メモリ領域の情報を登録する＿＿ｒｅｇｉｓｔｅｒ関数を追加する（ステップＳ２４）。具体的には、図７に示す命令２３４を検査対象プログラムに追加する。なお、ここでは、宣言２２０によってａｒｒａｙ１、ａｒｒａｙ２がグローバル変数として定義されているので、＿＿ｒｅｇｉｓｔｅｒ関数はメイン関数２３０の先頭に追加されている。
【００４６】
ステップＳ２４で書き換え部４が＿＿ｒｅｇｉｓｔｅｒ関数を追加すると、解釈部３は、プログラム記憶部２が記憶する検査対象プログラムを逐次解釈し、検査対象プログラムのうち、メモリ領域を解放する命令が記述されている位置を取得する（ステップＳ２５）。次に、書き換え部４は、プログラム記憶部２が記憶する検査対象プログラムのうち、解釈部３が取得した位置に記載されているメモリ領域を解放する命令の前に、当該メモリ領域の情報をメモリ領域テーブルから削除する＿＿ｕｎｒｅｇｉｓｔｅｒ関数を追加する（ステップＳ２６）。具体的には、図７に示す命令２３７を検査対象プログラムに追加する。なお、ここでは、メイン関数２３０を脱出することでａｒｒａｙ１、ａｒｒａｙ２が解放されるので、＿＿ｕｎｒｅｇｉｓｔｅｒ関数はメイン関数２３０の末尾に追加されている。
【００４７】
ステップＳ２６で書き換え部４が＿＿ｕｎｒｅｇｉｓｔｅｒ関数を追加すると、解釈部３は、プログラム記憶部２が記憶する検査対象プログラムを逐次解釈し、検査対象プログラムで用いられているポインタ変数が指すアドレスに格納されるデータの型を取得する（ステップＳ２７）。次に、書き換え部４は、プログラム記憶部２が記憶する検査対象プログラムに、取得した型のポインタ変数ｍａｉｎ及びｓｕｂを格納する拡張ポインタ構造体の宣言を追加する（ステップＳ２８）。具体的には、図７に示す宣言２４０を検査対象プログラムに追加する。なお、ここでは、図６に示す検査対象プログラムでｃｈａｒ型のポインタ変数ｐ、ｐ１、ｐ２が用いられているので、ｃｈａｒ型のポインタ変数ｍａｉｎ、ｓｕｂを格納し、ｃｈａｒ型のポインタ変数に対応する拡張ポインタ構造体であるｄｕａｌｐｔｒ＿ｃｈａｒ構造体を宣言している。
【００４８】
ステップＳ２８で書き換え部４が拡張ポインタ構造体の宣言を追加すると、解釈部３は、プログラム記憶部２が記憶する検査対象プログラムを逐次解釈し、検査対象プログラムのうち、ポインタ変数を用いた処理が記述されている位置を取得する（ステップＳ２９）。次に、書き換え部４は、プログラム記憶部２が記憶する検査対象プログラムのうち、解釈部３が取得した位置に記載されているポインタ変数を用いた処理を行う命令を、ステップＳ２８で宣言を追加した拡張ポインタ構造体を用いた処理に書き換える（ステップＳ３０）。具体的には、図６に示す命令２１１、２３１をそれぞれ図７に示す命令２１３、２３５に書き換える処理である。
【００４９】
ステップＳ３０で書き換え部４がポインタ変数を拡張ポインタ構造体に書き換えると、解釈部３は、プログラム記憶部２が記憶する検査対象プログラムを逐次解釈し、検査対象プログラムのうち、拡張ポインタ構造体を用いて算出した整数型変数の位置を取得する（ステップＳ３１）。拡張ポインタ構造体を用いた整数型変数の算出とは、例えば、ポインタ型変数（拡張ポインタ構造体）の減算や、ポインタ型変数（拡張ポインタ構造体）から整数型変数へのキャストがある。具体的には、解釈部３は、図６に示す命令２３２に含まれる整数型変数ｄが記述されている位置を取得する。
【００５０】
解釈部３は、ステップＳ３１で拡張ポインタ構造体を用いて算出した整数型変数の位置を取得できたか否かを判定する。つまり、拡張ポインタ構造体を用いて整数型変数を算出する命令が検査対象プログラムに存在するか否かを判定する（ステップＳ３２）。
解釈部３が、拡張ポインタ構造体を用いて整数型変数を算出する命令が検査対象プログラムに存在すると判定した場合（ステップＳ３２：ＹＥＳ）、書き換え部４は、プログラム記憶部２が記憶する検査対象プログラムに、整数型変数ｍａｉｎ（整数値）及びｓｕｂ（検査値）を格納する拡張整数型構造体ｄｕａｌ＿ｉｎｔの宣言を追加する（ステップＳ３３）。具体的には、図７に示す宣言２５０を検査対象プログラムに追加する。
【００５１】
書き換え部４は、ステップＳ３３で拡張整数型構造体の宣言を追加すると、プログラム記憶部２が記憶する検査対象プログラムのうち、ステップＳ３１で解釈部３が取得した位置に記載されている整数型変数を用いた処理を行う命令を、ステップＳ２８で宣言を追加した拡張整数型構造体を用いた処理に書き換える（ステップＳ３４）。
このとき、拡張整数型構造体の変数ｍａｉｎに、拡張ポインタ構造体の変数ｍａｉｎによって算出される値を格納する。また、拡張整数型構造体の変数ｓｕｂには、拡張ポインタ構造体の変数ｓｕｂによって算出される値を格納する。
また、拡張整数型構造体に整数値を加算する場合は、変数ｍａｉｎ及び変数ｓｕｂに同じ値を加算し、拡張ポインタ構造体同士の減算を行う場合は、変数ｍａｉｎに、拡張ポインタ構造体の変数ｍａｉｎ同士の減算結果を格納し、変数ｓｕｂに、拡張ポインタ構造体の変数ｓｕｂ同士の減算結果を格納する。
書き換え部４の処理は、具体的には、図６に示す命令２３２を図７に示す命令２３６に書き換える処理である。
【００５２】
ステップＳ３４で書き換え部４が整数型変数を拡張整数型構造体に書き換えると、解釈部３は、プログラム記憶部２が記憶する検査対象プログラムを逐次解釈し、検査対象プログラムのうち、拡張整数型構造体を用いて算出した整数型変数の位置を取得する（ステップＳ３５）。次に、解釈部３は、拡張整数型構造体を用いて算出した整数型変数の位置を取得できたか否かを判定する。つまり、拡張整数型構造体を用いて整数型変数を算出する命令が検査対象プログラムに存在するか否かを判定する（ステップＳ３６）。
【００５３】
解釈部３が、拡張整数型構造体を用いて整数型変数を算出する命令が検査対象プログラムに存在すると判定した場合（ステップＳ３６：ＹＥＳ）、書き換え部４は、プログラム記憶部２が記憶する検査対象プログラムのうち、ステップＳ３５で解釈部３が取得した位置に記載されている整数型変数を用いた処理を行う命令を、拡張整数型構造体を用いた処理に書き換える（ステップＳ３７）。書き換え部４が整数型変数を拡張整数型構造体に書き換えると、ステップＳ３５に戻り、再度、拡張整数型構造体を用いて整数型変数を算出する命令が検査対象プログラムに存在するか否かを判定する。
【００５４】
解釈部３は、ステップＳ３２で拡張ポインタ構造体を用いて整数型変数を算出する命令が検査対象プログラムに存在しないと判定した場合（ステップＳ３２：ＮＯ）、または、ステップＳ３６で拡張整数型構造体を用いて整数型変数を算出する命令が検査対象プログラムに存在しないと判定した場合（ステップＳ３６：ＮＯ）、拡張ポインタ構造体を用いたメモリアクセス命令が記述されている位置を取得する（ステップＳ３８）。次に、書き換え部４は、プログラム記憶部２が記憶する検査対象プログラムのうち、解釈部３が取得した位置に記載されている拡張ポインタ型構造体によるメモリアクセス命令の前に、当該メモリアクセスの境界検査を行う＿＿ｒａｎｇｅ＿ｃｈｅｃｋ関数を追加する（ステップＳ３９）。具体的には、図７に示す命令２１２を検査対象プログラムに追加する。
【００５５】
ステップＳ３９で書き換え部４が＿＿ｒａｎｇｅ＿ｃｈｅｃｋ関数を追加すると、出力部５は、プログラム記憶部２が記憶する検査対象プログラムを検査用プログラムとして出力する（ステップＳ４０）。
【００５６】
次に、上述した動作によって生成された第２の検査用プログラムを実行することで境界検査が実行できることを説明する。
実行装置が図７に示す第２の検査用プログラムを実行すると、まず、メイン関数２３０の命令２３４を実行する。これにより、ａｒｒａｙ１、ａｒｒａｙ２に識別番号が割り振られ、それぞれのアドレス範囲がメモリ領域テーブルに登録される。
次に、実行装置は命令２３５を実行する。これにより、拡張ポインタ構造体ｐ１、ｐ２が生成され、拡張ポインタ構造体ｐ１の変数ｍａｉｎに変数ａｒｒａｙ１の先頭アドレスが格納され、変数ｓｕｂに変数ｍａｉｎと変数ａｒｒａｙ１が示すメモリ領域に割り当てられた識別番号とを加算した値が格納される。また、拡張ポインタ構造体ｐ２の変数ｍａｉｎに変数ａｒｒａｙ２の先頭アドレスが格納され、変数ｓｕｂに変数ｍａｉｎと変数ａｒｒａｙ２が示すメモリ領域に割り当てられた識別番号とを加算した値が格納される。この処理は、図６に示す命令２３１に相当する。
【００５７】
次に、実行装置は、命令２３６を実行する。これにより、拡張整数型構造体ｄが生成され、拡張整数型構造体ｄの変数ｍａｉｎに拡張ポインタ構造体ｐ１、ｐ２の変数ｍａｉｎの差が格納され、変数ｓｕｂに拡張ポインタ構造体ｐ１、ｐ２の変数ｓｕｂの差が格納される。次に、拡張整数型構造体ｄの変数ｍａｉｎ及び変数ｓｕｂに２を加算する。次に、拡張ポインタ構造体ｐ１の変数ｍａｉｎに拡張整数型構造体ｄの変数ｍａｉｎを加算し、拡張ポインタ構造体ｐ１の変数ｓｕｂに拡張整数型構造体ｄの変数ｓｕｂを加算する。このとき、拡張ポインタ構造体ｐ１の変数ｍａｉｎには、変数ａｒｒａｙ２の先頭アドレス＋２の値が格納され、変数ｍａｉｎには、変数ａｒｒａｙ２の先頭アドレス＋２に変数ａｒｒａｙ２が示すメモリ領域に割り当てられた識別番号を加算した値が格納されている。また、この処理は、図６に示す命令２３２に相当する。
【００５８】
次に、実行装置は、命令２３３を実行することで、拡張ポインタ構造体ｐを引数として関数２１０を呼び出す。
関数２１０が呼び出されると、実行装置は、命令２１２を実行する。これにより、実行装置は、まず拡張ポインタ構造体ｐの変数ｓｕｂと変数ｍａｉｎとの差を算出し、算出した値を変数ｓｅｇ＿ｉｄに格納する。次に、変数ｓｅｇ＿ｉｄが格納する値と等しい値の識別番号がメモリ領域テーブルに格納されているか否かを判定する。変数ｓｕｂと変数ｍａｉｎとの差は、変数ａｒｒａｙ２のメモリ領域に識別番号と等しいため、実行装置は、次に、受け取ったポインタ値が当該識別番号に紐づけられたメモリ領域のサイズ内に収まっているか否かを判定する。変数ｍａｉｎに格納されているアドレスは、変数ａｒｒａｙ２の先頭アドレス＋２であり、変数ａｒｒａｙ２のサイズは８であるため、実行装置は、ポインタ値がメモリ領域のサイズ内に収まっていると判定する。従って、当該メモリアクセス命令が正しい記述であると判定する。
このように、第２の実施形態による検査用プログラム生成装置が生成した検査用プログラムを用いることで、従来の拡張ポインタ構造体を用いた検査用プログラムでは誤判定される、メモリアクセス先のアドレスを任意の整数演算により算出する処理を含むプログラムに対しても境界検査を実施することができる。
【００５９】
次に、整数型変数からポインタ変数へのキャストを行う処理を含むプログラムの例を示すプログラムリストを用いて、本発明の第２の実施形態による検査用プログラム生成装置の動作を説明する。
図８は、第３の検査対象プログラムを示すプログラムリストである。
図９は、検査用プログラム生成装置が生成する第３の検査用プログラムを示すプログラムリストである。
まず、第３の検査対象プログラムについて説明する。なお、本実施形態では、ｉｎｔ型整数のサイズは４バイト、ｓｈｏｒｔ型整数のサイズは２バイトであるものとして説明する。
図８に示す第３の検査対象プログラムは、ｉｎｔ型変数ａｄｄｒを引数として受け取り、当該変数をポインタ変数にキャストすることで得られるアドレスのデータに値１を書き込ませる命令３１１を実行する関数３１０が記述されている。また、ａｒｒａｙ１に１６バイトのメモリ領域を割り当てる宣言３２０が記述されている。また、メイン関数３３０には、命令３３１、命令３３２、命令３３３、命令３３４、命令３３５、命令３３６が記述されている。
命令３３１は、ポインタ変数ｐ１に変数ａｒｒａｙ１の先頭アドレスを格納する命令である。
命令３３２は、ポインタ変数ｐ１をｉｎｔ型整数にキャストした値をｉｎｔ型変数ａｄｄｒに格納し、得られたｉｎｔ型変数ａｄｄｒに２０を加算する命令である。
命令３３３は、ｉｎｔ型変数ａｄｄｒを引数として関数２１０を呼び出す命令である。
命令３３４は、ｉｎｔ型変数ａｄｄｒの下位２バイトを、ｓｈｏｒｔ型変数ａｄｄｒＬに格納し、ｉｎｔ型変数ａｄｄｒの上位２バイトを、ｓｈｏｒｔ型変数ａｄｄｒＨに格納する命令である。
命令３３５は、ｓｈｏｒｔ型変数ａｄｄｒＬをｉｎｔ型変数ａｄｄｒの下位２バイトに格納し、ｓｈｏｒｔ型変数ａｄｄｒＨを４バイトのｉｎｔ型変数ａｄｄｒの上位２バイトに格納するｉｎｔ型変数ａｄｄｒに格納し、そこから２０を減算する命令である。
命令３３６は、ｉｎｔ型変数ａｄｄｒを引数として関数２１０を呼び出す命令である。
【００６０】
実行装置が図８に示す第３の検査対象プログラムを実行すると、命令３３２により、変数ａｄｄｒには、ａｒｒａｙ１の先頭アドレス＋２０と等しい値が格納される。そして、命令３３３により、ａｄｄｒが示す数値をアドレスとする位置に値を書き込む動作を行う。このとき、ａｒｒａｙ１のサイズは１６であるため、命令３３３は、変数ａｒｒａｙ１の範囲を逸脱した不正な記述である。
次に、実行装置は、命令３３４により、変数ａｄｄｒの下位２バイトと上位２バイトとをそれぞれ変数ａｄｄｒＬ、ａｄｄｒＨに格納し、命令３３５により、変数ａｄｄｒＬ、ａｄｄｒＨに格納した値をそれぞれ変数ａｄｄｒの下位２バイトと上位２バイトに格納し、そこから２０を減算する。つまり、変数ａｄｄｒには、変数ａｒｒａｙ１の先頭アドレスと等しい値が格納される。そして、命令３３６により、変数ａｄｄｒが示す数値をアドレスとする位置に値を書き込む動作を行う。メモリアクセスは、ａｒｒａｙ１の先頭アドレスに対して行われるため、命令１３１は、ａｒｒａｙ１の正常範囲に値を書き込む正しい記述である。
【００６１】
上述したような第３の検査対象プログラムを入力すると、検査用プログラム生成装置は、図９に示す検査用プログラムを生成する。
検査用プログラムを生成する動作を、図５に示すフローチャートを用いて説明する。
図５に示すステップＳ２４で、書き換え部４は、図９に示す命令３３７を検査対象プログラムに追加する。次に、ステップＳ２６で、書き換え部４は、図９に示す命令３４４を検査対象プログラムに追加する。次に、ステップＳ２８で、書き換え部４は、図９に示す宣言３５０を検査対象プログラムに追加する。次に、ステップＳ３０で、書き換え部４は、図９に示す宣言３１２を追加し、図８に示す命令３１１、３３１をそれぞれ、図９に示す命令３３８、命令３１５に書き換える。
【００６２】
次に、ステップＳ３１で、解釈部３は、拡張ポインタ構造体を用いて算出した整数型変数として、図８に示す命令３３２に含まれる変数ａｄｄｒが記述されている位置を取得する。次に、ステップＳ３３で、書き換え部４は、図９に示す宣言３６０を検査対象プログラムに追加する。次に、ステップＳ３４で、書き換え部４は、図８に示す命令３１１、３３２をそれぞれ、図９に示す命令３１３、３３９に書き換える。
【００６３】
次に、ステップＳ３５で、解釈部３は、拡張整数型構造体を用いて算出した整数型変数として、図８に示す命令３３４に含まれる変数ａｄｄｒＬ，ａｄｄｒＨが記述されている位置を取得する。次に、ステップＳ３７で、書き換え部４は、図９に示す宣言３７０を検査対象プログラムに追加し、図８に示す命令３３４、３３５をそれぞれ、図９に示す命令３４１、３４２に書き換える。
次に、ステップＳ３９で、書き換え部４は、図９に示す命令３１４を追加する。そして、ステップＳ４０で、出力部５は、検査対象プログラムを検査用プログラムとして出力する。
【００６４】
次に、図９に示す検査用プログラムを実行することで境界検査が実行できることを説明する。
実行装置が図９に示す検査用プログラムを実行すると、まず、メイン関数３３０の命令３３７を実行する。これにより、変数ａｒｒａｙ１に識別番号が割り振られ、変数ａｒｒａｙ１のアドレス範囲がメモリ領域テーブルに登録される。
次に、実行装置は命令３３８を実行する。これにより、拡張ポインタ構造体ｐ１が生成され、拡張ポインタ構造体ｐ１の変数ｍａｉｎに変数ａｒｒａｙ１の先頭アドレスが格納され、変数ｓｕｂに変数ｍａｉｎと変数ａｒｒａｙ１が示すメモリ領域に割り当てられた識別番号とを加算した値が格納される。この処理は、図８に示す命令３３１に相当する。
【００６５】
次に、実行装置は、命令３３９を実行する。これにより、拡張整数型構造体ａｄｄｒが生成され、拡張整数型構造体ａｄｄｒの変数ｍａｉｎに拡張ポインタ構造体ｐ１の変数ｍａｉｎを整数型にキャストした値が格納され、変数ｓｕｂに拡張ポインタ構造体ｐ１の変数ｓｕｂを整数型にキャストした値が格納される。次に、拡張整数型構造体ａｄｄｒの変数ｍａｉｎ及び変数ｓｕｂに２０を加算する。この処理は、図８に示す命令３３２に相当する。
【００６６】
次に、実行装置は、命令３４０を実行することで、拡張整数型構造体ａｄｄｒを引数として関数３１０を呼び出す。
関数３１０が呼び出されると、実行装置は、命令３１３を実行する。これにより、実行装置は、引数として与えられた拡張整数型構造体ａｄｄｒの変数ｍａｉｎを拡張ポインタ構造体ｐの変数ｍａｉｎに格納し、拡張整数型構造体ａｄｄｒの変数ｓｕｂを拡張ポインタ構造体ｐの変数ｓｕｂに格納する。
次に、実行装置は、命令３１４を実行する。これにより、実行装置は、まず拡張ポインタ構造体ｐの変数ｓｕｂと変数ｍａｉｎとの差を算出し、算出した値を変数ｓｅｇ＿ｉｄに格納する。次に、変数ｓｅｇ＿ｉｄが格納する値と等しい値の識別番号がメモリ領域テーブルに格納されているか否かを判定する。変数ｓｕｂと変数ｍａｉｎとの差は、変数ａｒｒａｙ１のメモリ領域に識別番号と等しいため、実行装置は、次に、受け取ったポインタ値が当該識別番号に紐づけられたメモリ領域のサイズ内に収まっているか否かを判定する。変数ｍａｉｎに格納されているアドレスは、変数ａｒｒａｙ１の先頭アドレス＋２０であり、変数ａｒｒａｙ１のサイズは１６であるため、実行装置は、ポインタ値がメモリ領域のサイズ内に収まっていないと判定する。従って、当該メモリアクセス命令が不正な記述であると判定する。
【００６７】
次に、実行装置は、命令３４１を実行する。これにより、実行装置は、拡張整数型構造体ａｄｄｒＬの変数ｍａｉｎに拡張整数型構造体ａｄｄｒの変数ｍａｉｎの下位２バイトを格納し、拡張整数型構造体ａｄｄｒＬの変数ｓｕｂに拡張整数型構造体ａｄｄｒの変数ｓｕｂの下位２バイトを格納する。また、実行装置は、拡張整数型構造体ａｄｄｒＨの変数ｍａｉｎに拡張整数型構造体ａｄｄｒの変数ｍａｉｎの上位２バイトを格納し、拡張整数型構造体ａｄｄｒＨの変数ｓｕｂに拡張整数型構造体ａｄｄｒの変数ｓｕｂの上位２バイトを格納する。
次に、実行装置は、命令３４２を実行する。これにより、実行装置は、拡張整数型構造体ａｄｄｒの変数ｍａｉｎの上位２バイトに拡張整数型構造体ａｄｄｒＨの変数ｍａｉｎの値を格納し、下位２バイトに拡張整数型構造体ａｄｄｒＬの変数ｍａｉｎの値を格納し、そこから２０を減算する。また、実行装置は、拡張整数型構造体ａｄｄｒの変数ｓｕｂの上位２バイトに拡張整数型構造体ａｄｄｒＨの変数ｍａｉｎの値を格納し、下位２バイトに拡張整数型構造体ａｄｄｒＬの変数ｓｕｂの値を格納し、そこから２０を減算する。
【００６８】
次に、実行装置は、命令３４３を実行することで、拡張整数型構造体ａｄｄｒを引数として関数３１０を呼び出す。
関数３１０が呼び出されると、実行装置は、命令３１３を実行する。これにより、実行装置は、引数として与えられた拡張整数型構造体ａｄｄｒの変数ｍａｉｎを拡張ポインタ構造体ｐの変数ｍａｉｎに格納し、拡張整数型構造体ａｄｄｒの変数ｓｕｂを拡張ポインタ構造体ｐの変数ｓｕｂに格納する。
次に、実行装置は、命令３１４を実行する。これにより、実行装置は、まず拡張ポインタ構造体ｐの変数ｓｕｂと変数ｍａｉｎとの差を算出し、算出した値を変数ｓｅｇ＿ｉｄに格納する。次に、変数ｓｅｇ＿ｉｄが格納する値と等しい値の識別番号がメモリ領域テーブルに格納されているか否かを判定する。変数ｓｕｂと変数ｍａｉｎとの差は、変数ａｒｒａｙ１のメモリ領域に識別番号と等しいため、実行装置は、次に、受け取ったポインタ値が当該識別番号に紐づけられたメモリ領域のサイズ内に収まっているか否かを判定する。変数ｍａｉｎに格納されているアドレスは、変数ａｒｒａｙ１の先頭アドレスであるため、実行装置は、ポインタ値がメモリ領域のサイズ内に収まっていると判定する。従って、当該メモリアクセス命令が正しい記述であると判定する。
【００６９】
なお、メモリ領域の配置アドレスに依存してなされる整数型演算としては、図６、図８に例示した以外の演算を含んでいても良い。以下に理由を述べる。
変換後の検査用プログラムにおける拡張ポインタ構造体と拡張整数型構造体の検査値は、メモリ領域の配置アドレスを実際の配置から変更し、各メモリ領域の先頭アドレスにその識別番号を加算したアドレスに配置したと仮定してプログラムを実行した場合に得られる演算結果を表している。適切なメモリアクセスを行う正しいプログラムは、メモリ領域の配置アドレスを変更したとしても、アクセスを行うメモリ領域と、メモリ領域内の相対的な位置は不変であるため、メモリアクセス時の拡張ポインタ構造体の検査値は、当該構造体のポインタ値に識別番号を加算したものに等しい。よって、上述したようにメモリアクセス前に拡張ポインタ構造体の検査値からポインタ値を引くことで参照先のメモリ領域を特定し、境界検査を行うことができる。この性質は、アドレス計算の過程でなされる途中の演算式によらないため、図６と図８の例以外であっても、検査を行うことができることを示している。
このように、第２の実施形態による検査用プログラム生成装置が生成した検査用プログラムを用いることで、従来の拡張ポインタ構造体を用いた検査用プログラムでは誤判定される、整数型変数からポインタ変数へのキャストを行う処理を含むプログラムに対しても境界検査を実施することができる。
【実施例３】
【００７０】
次に、本発明の第３の実施形態について詳しく説明する。
Ｃ言語では、ポインタ値の減算で得られる整数や、「ポインタ値＋整数」によって加算するオフセット値は、ポインタ値が参照するメモリ領域を示す変数の型のサイズを基準に計算される。例えば、ｉｎｔ型変数の先頭アドレスを示すポインタ値に１を加算することで得られるアドレスは、ｉｎｔ型変数の先頭アドレスの１番地先ではなく４番地先のアドレスとなる。このため、上述した本発明の第１の実施形態、及び第２の実施形態では、拡張ポインタ構造体の変数ｓｕｂとｍａｉｎとの差によって算出する値が、ポインタ値が参照するメモリ領域を示す変数の型のサイズに依存するため、ポインタの型の変換を行うプログラムにおいて誤ったエラー情報が出力されてしまう。
これを解決するため、第３の実施形態では、第２の実施形態による検査用プログラム生成装置を拡張し、ポインタの型の変換を行うプログラムに対しても境界検査を実施することができるようにしたものについて説明する。
【００７１】
第３の実施形態による検査用プログラム生成装置は、第２の実施形態による検査用プログラム生成装置と同じ構成とし、書き換え部４が追加するモジュールにおいて、＿＿ｒｅｇｉｓｔｅｒ関数に、メモリ領域に識別番号を割り振るとき、当該識別番号を当該メモリ領域に格納されるデータの型のサイズの整数倍の数値とする命令が記述されることを特徴とする。
【００７２】
次に、具体的な例を示すプログラムリストを用いて本発明の第３の実施形態による検査用プログラム生成装置の動作を説明する。
図１０は、検査用プログラム生成装置の動作を示す第３のフローチャートである。
図１１は、第４の検査対象プログラムを示すプログラムリストである。
図１２は、検査用プログラム生成装置が生成する第４の検査用プログラムを示すプログラムリストである。なお、本実施形態では、ｉｎｔ型のサイズは４バイト、ｃｈａｒ型のサイズは１バイトであるものとする。
まず、第４の検査対象プログラムについて説明する。
図１１に示す第４の検査対象プログラムは、変数ａｄｄｒを引数として受け取り、当該変数ａｄｄｒをｃｈａｒ型のポインタ変数にキャストすることで得られるアドレスのデータに値１を書き込ませる命令４１１を実行する関数４１０が記述されている。また、ａｒｒａｙ３にｉｎｔ型整数１６個分のメモリ領域を割り当てる宣言４２０が記述されている。また、メイン関数４３０には、命令４３１、命令４３２、命令４３３が記述されている。
命令４３１は、ｉｎｔ型のポインタ変数ｐ１に変数ａｒｒａｙ３の先頭アドレスを格納する命令である。
命令４３２は、ｉｎｔ型整数ａｄｄｒとして、ポインタ変数ｐ１をｉｎｔ型整数にキャストした値を格納する命令である。
命令４３３は、ポインタ変数ｐ１を引数に関数２１０を呼び出す命令である。
【００７３】
つまり、実行装置が図１１に示す第４の検査対象プログラムを実行すると、実行装置は、宣言４２０によってｉｎｔ型変数の配列として確保されたａｒｒａｙ３を、関数４１０命令４１１を実行することで、ｃｈａｒ型のポインタを用いてアクセスすることとなる。命令４１１では、ポインタ変数ｐは、ａｒｒａｙ３の先頭アドレスを示しているため、当該メモリアクセスは正しい記述である。
【００７４】
次に、検査用プログラム生成装置の動作を説明する。
まず、利用者が検査用プログラム生成装置に検査対象プログラムの入力を行うと、入力部１１は、検査対象プログラムの入力を受け付け、当該検査対象プログラムをプログラム記憶部１２に登録する（ステップＳ５１）。
【００７５】
入力部１がプログラム記憶部２に検査対象プログラムを登録すると、書き換え部４は、プログラム記憶部２が記憶する検査対象プログラムに、メモリ領域の管理を行う関数及び変数を格納したモジュールを追加する（ステップＳ５２）。
ここで、追加するモジュールに記述されている関数の各々の詳細を説明する。
＿＿ｒｅｇｉｓｔｅｒ関数は、引数として変数名と当該変数のサイズに加えて、当該変数の型のサイズを受け取る。引数を受け取ると、受け取った変数名が示すメモリ領域に対し、メモリ領域テーブルに登録されていない識別番号を付与する。この際、識別番号は、引数として与えられた変数の型のサイズの整数倍の数値とする。＿＿ｒｅｇｉｓｔｅｒ関数は、識別番号を付与すると、メモリ領域テーブルに、付与した識別番号に紐づけて、メモリ領域の先頭アドレスと、当該メモリ領域のサイズとを登録する。
＿＿ｕｎｒｅｇｉｓｔｅｒ関数は、引数として変数名を受け取る。引数を受け取ると、メモリ領域テーブルから、受け取った変数名が示すメモリ領域に紐づけられた情報を削除する。
＿＿ｓｅｇ＿ｉｄ関数は、引数として変数名を受け取る。引数を受け取ると、メモリ領域テーブルから、受け取った変数名が示すメモリ領域の識別番号を取得する。
＿＿ｒａｎｇｅ＿ｃｈｅｃｋ関数は、引数として拡張ポインタ構造体のポインタ値と、検査値とポインタ値との差をポインタ値が参照するデータの型のサイズで乗算した値とを受け取る。引数を受け取ると、受け取った検査値とポインタ値との差と等しい値の識別番号がメモリ領域テーブルに格納されているか否かを判定し、格納されている場合は、受け取ったポインタ値が当該識別番号に紐づけられたメモリ領域のサイズ内に収まっているか否かを判定する。ポインタ値がメモリ領域のサイズ内に収まっていると判定された場合に、当該メモリアクセス命令が正しい記述であると判定する。
【００７６】
ステップＳ５２で書き換え部４が関数及び変数の記述を追加すると、解釈部３は、プログラム記憶部２が記憶する検査対象プログラムを逐次解釈し、検査対象プログラムのうち、メモリ領域を確保する命令が記述されている位置を取得する（ステップＳ５３）。次に、書き換え部４は、プログラム記憶部２が記憶する検査対象プログラムのうち、解釈部３が取得した位置に記載されているメモリ領域を確保する命令の次に、当該メモリ領域に識別番号を付与し、メモリ領域テーブルに当該メモリ領域の情報を登録する＿＿ｒｅｇｉｓｔｅｒ関数を追加する（ステップＳ５４）。具体的には、図１２に示す命令４３４を検査対象プログラムに追加する。
【００７７】
ステップＳ５４で書き換え部４が＿＿ｒｅｇｉｓｔｅｒ関数を追加すると、解釈部３は、プログラム記憶部２が記憶する検査対象プログラムを逐次解釈し、検査対象プログラムのうち、メモリ領域を解放する命令が記述されている位置を取得する（ステップＳ５５）。次に、書き換え部４は、プログラム記憶部２が記憶する検査対象プログラムのうち、解釈部３が取得した位置に記載されているメモリ領域を解放する命令の前に、当該メモリ領域の情報をメモリ領域テーブルから削除する＿＿ｕｎｒｅｇｉｓｔｅｒ関数を追加する（ステップＳ５６）。具体的には、図１２に示す命令４３７を検査対象プログラムに追加する。
【００７８】
ステップＳ５６で書き換え部４が＿＿ｕｎｒｅｇｉｓｔｅｒ関数を追加すると、解釈部３は、プログラム記憶部２が記憶する検査対象プログラムを逐次解釈し、検査対象プログラムで用いられているポインタ変数が指すアドレスに格納されるデータの型を取得する（ステップＳ５７）。次に、書き換え部４は、プログラム記憶部２が記憶する検査対象プログラムに、取得した型のポインタ変数ｍａｉｎ及びｓｕｂを格納する拡張ポインタ構造体の宣言を追加する（ステップＳ５８）。具体的には、図１２に示す宣言４４０、４５０を検査対象プログラムに追加する。なお、ここでは、図１１に示す検査対象プログラムの命令４１１でｃｈａｒ型のポインタ変数ｐが用いられ、命令４３１でｉｎｔ型のポインタ変数ｐ１が用いられているので、ｃｈａｒ型のポインタ変数に対応する拡張ポインタ構造体であるｄｕａｌｐｔｒ＿ｃｈａｒ構造体、及びｉｎｔ型のポインタ変数に対応する拡張ポインタ構造体であるｄｕａｌｐｔｒ＿ｉｎｔ構造体を宣言している。
【００７９】
ステップＳ５８で書き換え部４が拡張ポインタ構造体の宣言を追加すると、解釈部３は、プログラム記憶部２が記憶する検査対象プログラムを逐次解釈し、検査対象プログラムのうち、ポインタ変数を用いた処理が記述されている位置を取得する（ステップＳ５９）。次に、書き換え部４は、プログラム記憶部２が記憶する検査対象プログラムのうち、解釈部３が取得した位置に記載されているポインタ変数を用いた処理を行う命令を、ステップＳ５８で宣言を追加した拡張ポインタ構造体を用いた処理に書き換える（ステップＳ６０）。
このとき、拡張ポインタ構造体の変数ｍａｉｎに、書き換え前のポインタ変数が示す値を格納する。また、拡張ポインタ構造体の変数ｓｕｂには、変数ｍａｉｎが格納する値に、アクセス対象となるメモリ領域の識別番号を、当該メモリ領域を示す変数の型のサイズで除算した値を加算した値を格納する。このとき、アクセス対象となるメモリ領域の識別番号は、上述した＿＿ｓｅｇ＿ｉｄ関数によってメモリ領域テーブルから取得することができる。
また、ポインタ変数に対する演算は、全て拡張ポインタ型構造体の変数ｍａｉｎに対する演算として書き換える。このとき、変数ｍａｉｎの値が変更された場合は、変数ｓｕｂと変数ｍａｉｎとの差が、アクセス対象となるメモリ領域の識別番号を、当該メモリ領域を示す変数の型のサイズで除算した値となるように命令を追加する。
具体的には、書き換え部４は、図１１に示す検査対象プログラムの命令４１１、４３１を、それぞれ図１２に示す命令４１５、４３５に書き換える処理を行う。
【００８０】
ステップＳ６０で書き換え部４がポインタ変数を拡張ポインタ構造体に書き換えると、解釈部３は、プログラム記憶部２が記憶する検査対象プログラムを逐次解釈し、検査対象プログラムのうち、拡張ポインタ構造体を用いて算出した整数型変数の位置を取得する（ステップＳ６１）。具体的には、解釈部３は、図１１に示す命令４３２に含まれる整数型変数ａｄｄｒが記述されている位置を取得する。
【００８１】
解釈部３は、ステップＳ６１で拡張ポインタ構造体を用いて算出した整数型変数の位置を取得できたか否かを判定する。つまり、拡張ポインタ構造体を用いて整数型変数を算出する命令が検査対象プログラムに存在するか否かを判定する（ステップＳ６２）。
解釈部３が、拡張ポインタ構造体を用いて整数型変数を算出する命令が検査対象プログラムに存在すると判定した場合（ステップＳ６２：ＹＥＳ）、書き換え部４は、プログラム記憶部２が記憶する検査対象プログラムに、整数型変数ｍａｉｎ及びｓｕｂを格納する拡張整数型構造体の宣言を追加する（ステップＳ６３）。具体的には、図１２に示す宣言４６０を検査対象プログラムに追加する。
【００８２】
書き換え部４は、ステップＳ６３で拡張整数型構造体の宣言を追加すると、プログラム記憶部２が記憶する検査対象プログラムのうち、ステップＳ６１で解釈部３が取得した位置に記載されている整数型変数を用いた処理を行う命令を、ステップＳ５８で宣言を追加した拡張整数型構造体を用いた処理に書き換える（ステップＳ６４）。具体的には、図１１に示す命令４１１、４３２をそれぞれ、図１２に示す命令４１３、４３６に書き換える処理である。
【００８３】
ステップＳ６４で書き換え部４が整数型変数を拡張整数型構造体に書き換えると、解釈部３は、プログラム記憶部２が記憶する検査対象プログラムを逐次解釈し、検査対象プログラムのうち、拡張整数型構造体を用いて算出した整数型変数の位置を取得する（ステップＳ６５）。次に、解釈部３は、拡張整数型構造体を用いて算出した整数型変数の位置を取得できたか否かを判定する。つまり、拡張整数型構造体を用いて整数型変数を算出する命令が検査対象プログラムに存在するか否かを判定する（ステップＳ６６）。
【００８４】
解釈部３が、拡張整数型構造体を用いて整数型変数を算出する命令が検査対象プログラムに存在すると判定した場合（ステップＳ６６：ＹＥＳ）、書き換え部４は、プログラム記憶部２が記憶する検査対象プログラムのうち、ステップＳ３５で解釈部３が取得した位置に記載されている整数型変数を用いた処理を行う命令を、拡張整数型構造体を用いた処理に書き換える（ステップＳ６７）。書き換え部４が整数型変数を拡張整数型構造体に書き換えると、ステップＳ６５に戻り、再度、拡張整数型構造体を用いて整数型変数を算出する命令が検査対象プログラムに存在するか否かを判定する。
【００８５】
解釈部３は、ステップＳ６２で拡張ポインタ構造体を用いて整数型変数を算出する命令が検査対象プログラムに存在しないと判定した場合（ステップＳ６２：ＮＯ）、または、ステップＳ６６で拡張整数型構造体を用いて整数型変数を算出する命令が検査対象プログラムに存在しないと判定した場合（ステップＳ６６：ＮＯ）、拡張ポインタ構造体を用いたメモリアクセス命令が記述されている位置を取得する（ステップＳ６８）。次に、書き換え部４は、プログラム記憶部２が記憶する検査対象プログラムのうち、解釈部３が取得した位置に記載されている拡張ポインタ型構造体によるメモリアクセス命令の前に、当該メモリアクセスの境界検査を行う＿＿ｒａｎｇｅ＿ｃｈｅｃｋ関数を追加する（ステップＳ６９）。この際、＿＿ｒａｎｇｅ＿ｃｈｅｃｋ関数に、拡張ポインタ構造体のポインタ値と、検査値とポインタ値との差をポインタ値が参照するデータの型のサイズで乗算した値とを引数として渡す。具体的には、図１２に示す命令４１４を検査対象プログラムに追加する。
【００８６】
ステップＳ６９で書き換え部４が＿＿ｒａｎｇｅ＿ｃｈｅｃｋ関数を追加すると、出力部５は、プログラム記憶部２が記憶する検査対象プログラムを検査用プログラムとして出力する（ステップＳ７０）。
【００８７】
次に、上述した動作によって生成された第４の検査用プログラムを実行することで境界検査が実行できることを説明する。
実行装置が図１２に示す第４の検査用プログラムを実行すると、まず、メイン関数４３０の命令４３４を実行する。これにより、ａｒｒａｙ３に識別番号が割り振られ、それぞれのアドレス範囲がメモリ領域テーブルに登録される。このとき、ｉｎｔ型整数のサイズが４バイトであるため、ａｒｒａｙ３の識別番号は、４の整数倍の値となる。
次に、実行装置は命令４３５を実行する。これにより、ｉｎｔ型拡張ポインタ構造体ｐ１が生成され、ｉｎｔ型拡張ポインタ構造体ｐ１の変数ｍａｉｎに変数ａｒｒａｙ３の先頭アドレスが格納され、変数ｓｕｂに、変数ｍａｉｎと変数ａｒｒａｙ３が示すメモリ領域に割り当てられた識別番号をｉｎｔ型のサイズ４で除算した値とを加算した値が格納される。この処理は、図１１に示す命令４３１に相当する。
【００８８】
次に、実行装置は、命令４３６を実行する。これにより、拡張整数型構造体ａｄｄｒが生成され、拡張整数型構造体ａｄｄｒの変数ｍａｉｎにｉｎｔ型拡張ポインタ構造体ｐ１の変数ｍａｉｎを整数型にキャストした値が格納され、変数ｓｕｂにｉｎｔ型拡張ポインタ構造体ｐ１の変数ｓｕｂを整数型にキャストした値が格納される。この処理は、図１１に示す命令４３２に相当する。
【００８９】
次に、実行装置は、命令４３３を実行することで、拡張整数型構造体ａｄｄｒを引数として関数４１０を呼び出す。
関数４１０が呼び出されると、実行装置は、命令４１３を実行する。これにより、実行装置は、引数として与えられた拡張整数型構造体ａｄｄｒの変数ｍａｉｎをｃｈａｒ型拡張ポインタ構造体ｐの変数ｍａｉｎに格納し、拡張整数型構造体ａｄｄｒの変数ｓｕｂをｃｈａｒ型拡張ポインタ構造体ｐの変数ｓｕｂに格納する。
次に、実行装置は、命令４１４を実行する。これにより、実行装置は、まずｃｈａｒ型拡張ポインタ構造体ｐの変数ｓｕｂと変数ｍａｉｎとの差を算出し、算出した値にｃｈａｒ型のサイズ１を乗算した値を変数ｓｅｇ＿ｉｄに格納する。次に、変数ｓｅｇ＿ｉｄが格納する値と等しい値の識別番号がメモリ領域テーブルに格納されているか否かを判定する。ｃｈａｒ型文字は、ｉｎｔ型整数の４分の１のサイズであるため、ｃｈａｒ型拡張ポインタ構造体ｐの変数ｓｕｂと変数ｍａｉｎとの差をｃｈａｒ型のサイズ１で乗算した値は、ｉｎｔ型拡張ポインタ構造体ｐ１の変数ｓｕｂと変数ｍａｉｎとの差の４倍となる。すなわち、ｃｈａｒ型拡張ポインタ構造体ｐの変数ｓｕｂと変数ｍａｉｎとの差をｃｈａｒ型のサイズ１で乗算した値は、変数ａｒｒａｙ３のメモリ領域に識別番号と等しい。そのため、実行装置は、次に、受け取ったポインタ値が当該識別番号に紐づけられたメモリ領域のサイズ内に収まっているか否かを判定する。変数ｍａｉｎに格納されているアドレスは、変数ａｒｒａｙ３の先頭アドレスであるため、実行装置は、ポインタ値がメモリ領域のサイズ内に収まっていると判定する。従って、当該メモリアクセス命令が正しい記述であると判定する。
このように、第３の実施形態による検査用プログラム生成装置が生成した検査用プログラムを用いることで、第１の実施形態、及び第２の実施形態検査用プログラムでは誤判定される、ポインタの型の変換を行うプログラムに対しても境界検査を実施することができる。
【００９０】
以上、図面を参照してこの発明の一実施形態について詳しく説明してきたが、具体的な構成は上述のものに限られることはなく、この発明の要旨を逸脱しない範囲内において様々な設計変更等をすることが可能である。
なお、本実施形態では、検査用プログラム生成装置が、静的なメモリ領域に格納されるグローバル変数の境界検査を行う検査用プログラムを生成する例を説明したが、これに限られず、スタック領域の一時変数や、ヒープ領域のメモリのアドレスの境界検査を行う検査用プログラムを生成することもできる。
【００９１】
図１３は、第５の検査対象プログラムを示すプログラムリストである。
図１４は、検査用プログラム生成装置が生成する第５の検査用プログラムを示すプログラムリストである。
図１３に示す第５の検査対象プログラムにおいて、関数５２０では、まず、命令５２２によって、ｃｈａｒ型の変数ａが一時的なスタックメモリ上に確保される。次に、命令５２３における＆演算子により、変数ａへのアドレスがｐ１に代入され、命令５２４による関数５１０の呼び出しによって、変数ａに対するメモリアクセスが行われる。また、命令５２５による関数５１０の呼び出しによって、変数ａの次のアドレスへのメモリアクセスが行われる。この際、命令５２４によるメモリアクセスは正常なアクセスであり、命令５２５によるメモリアクセスは不正なアクセスである。
【００９２】
図１４に示す第５の検査用プログラムにおいて、関数５２０では、命令５２２でスタック上に変数ａが確保された後、命令５２７により、＿＿ｒｅｇｉｓｔｅｒ関数を呼び出してメモリ領域テーブルに変数ａのメモリ領域を登録し、適切な識別番号を変数ａに割り当てる。また、関数５２０を抜けてメモリ領域が自動的に解放される前には、命令５２９によりメモリ領域テーブルから登録を解除する。
上述した以外の動作は、静的なメモリ領域へのメモリアクセスの検査と同じである。
拡張ポインタ構造体ｐ１の変数ｍａｉｎとｓｕｂの差が、割り当てられた変数ａの識別番号を保存しているため、同様に検査が可能であり、命令５２３による関数５１０の呼び出しは正常なアクセス、命令５２４による関数５１０の呼び出しは不正なアクセスと判定することができる。
【００９３】
図１３に示す第５の検査対象プログラムにおいて、関数５３０では、まず、命令５３１によるｍａｌｌｏｃ関数の呼び出しにより、０ｘ１０バイトのメモリ領域が実行時にヒープから確保されて、命令５３４によるｆｒｅｅ関数の呼び出しにより解放される。
【００９４】
図１４に示す第５の検査用プログラムにおいて、関数５３０では、命令５３５によって、ｍａｌｌｏｃ関数の呼び出し後に＿＿ｒｅｇｉｓｔｅｒ関数を呼び出すことによりメモリ領域テーブルへの領域の登録を行う。そして、命令５３６によって、ｆｒｅｅ関数の呼び出し前に＿＿ｕｎｒｅｇｉｓｔｅｒ関数を呼び出すことにより、メモリ領域テーブルからの登録の解除が行われる。
上述した以外の動作は、静的なメモリ領域へのメモリアクセスの検査と同じである。
拡張ポインタ構造体ｐ２の変数ｍａｉｎとｓｕｂメンバの差が、割り当てられた領域の識別番号を保存しているため、同様に検査が可能であり、命令５３２による関数５１０の呼び出しは正常なアクセス、命令５３３による関数５１０の呼び出しは不正なアクセスと判定することができる。
【００９５】
このように、スタック上に置かれた変数へのメモリアクセスや、ヒープから動的に確保された領域へのメモリアクセスを含む被検査プログラムについては、メモリ領域の確保と解放のタイミングに合わせて適切に領域の登録と解除を行う命令を挿入することで、静的なメモリ領域と同様に検査を行うことが可能である。
【００９６】
上述の検査用プログラム生成装置は内部に、コンピュータシステムを有している。そして、上述した各処理部の動作は、プログラムの形式でコンピュータ読み取り可能な記録媒体に記憶されており、このプログラムをコンピュータが読み出して実行することによって、上記処理が行われる。ここでコンピュータ読み取り可能な記録媒体とは、磁気ディスク、光磁気ディスク、ＣＤ−ＲＯＭ、ＤＶＤ−ＲＯＭ、半導体メモリ等をいう。また、このコンピュータプログラムを通信回線によってコンピュータに配信し、この配信を受けたコンピュータが当該プログラムを実行するようにしても良い。
【００９７】
また、上記プログラムは、前述した機能の一部を実現するためのものであっても良い。さらに、前述した機能をコンピュータシステムにすでに記録されているプログラムとの組み合わせで実現できるもの、いわゆる差分ファイル（差分プログラム）であっても良い。
【符号の説明】
【００９８】
１…入力部  ２…プログラム記憶部  ３…解釈部  ４…書き換え部  ５…出力部
【図１】
2010277302.tif 000003
【図２】
2010277302.tif 000004
【図３】
2010277302.tif 000005
【図４】
2010277302.tif 000006
【図５】
2010277302.tif 000007
【図６】
2010277302.tif 000008
【図７】
2010277302.tif 000009
【図８】
2010277302.tif 000010
【図９】
2010277302.tif 000011
【図１０】
2010277302.tif 000012
【図１１】
2010277302.tif 000013
【図１２】
2010277302.tif 000014
【図１３】
2010277302.tif 000015
【図１４】
2010277302.tif 000016
【図１５】
2010277302.tif 000017
【図１６】
2010277302.tif 000018
【図１７】
2010277302.tif 000019
【図１８】
2010277302.tif 000020