(57)【要約】【課題】  プログラマに一切負担をかけずに、検出漏れなく、少ない誤検出で、バッファオーバーフロー脆弱性を検出する。【解決手段】  解析対象となるプログラムから、確保された領域を示す領域式と、前記領域式が示す領域においてアクセスする位置を指定する指数式とを含む領域アクセス式を検出し、前記領域式が示す領域のサイズ式を検出し、前記領域アクセス式を含む命令を実行すると前記領域式が示す領域外へのアクセスとなるバッファオーバーフローが発生するバッファオーバーフロー条件を前記指数式と前記サイズ式とを用いて算出し、前記ソースプログラムの上流側に配置された命令から前記領域アクセス式を含む命令へ至るまでの命令の実行経路を特定し、前記実行経路上に配置された代入命令に基づき前記バッファオーバーフロー条件を前記実行経路の上流へ向けて遡及させ、前記バッファオーバーフロー条件の上流での表現を求める。【選択図】  図１
2006031363.tif 000002
【特許請求の範囲】
【請求項１】
解析対象となるプログラムから、確保された領域を示す領域式と、前記領域式が示す領域においてアクセスする位置を指定する指数式とを含む領域アクセス式を検出する領域アクセス式検出ステップと、
前記領域式が示す領域のサイズ式を検出する領域サイズ検出ステップと、
前記領域アクセス式を含む命令を実行すると前記領域式が示す領域外へのアクセスとなるバッファオーバーフローが発生するバッファオーバーフロー条件を、前記指数式と前記サイズ式とを用いて算出する条件算出ステップと、
前記プログラムの上流側に配置された命令から前記領域アクセス式を含む命令へ至るまでの命令の実行経路を特定し、前記実行経路上に配置された代入命令に基づき前記バッファオーバーフロー条件を前記実行経路の上流へ向けて遡及させ、前記バッファオーバーフロー条件の上流での表現を求める遡及ステップと、
をコンピュータに実行させるバッファオーバーフロー脆弱性検出プログラム。
【請求項２】
前記遡及ステップは、前記実行経路上に分岐条件命令が含まれる場合は、前記実行経路に対応する分岐条件と、前記バッファオーバーフロー条件とを比較し、前記分岐条件と前記バッファオーバーフロー条件とが集合論的に重複する場合は、重複部分に基づき新たなバッファオーバーフロー条件を生成し遡及を続けることを特徴とする請求項１に記載のプログラム。
【請求項３】
前記遡及ステップは、前記実行経路上に分岐条件命令が含まれる場合は、前記実行経路に対応する分岐条件と、前記バッファオーバーフロー条件とを比較し、前記分岐条件と前記バッファオーバーフロー条件とが矛盾する場合は、前記実行経路に沿って命令を実行した場合前記バッファオーバーフローは発生しない旨を判断することを特徴とする請求項１又は２に記載のプログラム。
【請求項４】
前記遡及ステップは、前記領域アクセス式を含む命令へ至る実行経路が複数存在する場合は各実行経路についてそれぞれ前記バッファオーバーフロー条件を遡及させることを特徴とする請求項１乃至３のいずれかに記載のプログラム。
【請求項５】
ソースプログラムを字句解析及び構文解析する解析ステップと、
前記解析ステップによる解析結果に基づいて、
任意個数の宣言コードを冒頭に含み、任意個数の代入命令を中間に含み、多くとも１つの条件分岐命令を末尾に含み、実行は冒頭から始まり末尾まで直列実行されるユニット、が複数集まって作るユニット遷移グラフで、プログラムの実行はユニット間の遷移とユニット内の前記直列実行として表されるユニット遷移グラフであって、前記条件分岐命令を含むユニットから次のユニットへの遷移は、前記条件分岐命令の分岐条件に応じて決定されるユニット遷移グラフを生成するユニット遷移グラフ生成ステップと、
確保された領域を示す領域式と、前記領域においてアクセスする位置を指定する指数式とを含む領域アクセス式を前記ユニットから検出する領域アクセス式検出ステップと、
前記領域式が示す領域のサイズ式を検出する領域サイズ検出ステップと、
前記領域アクセス式を含む命令を実行すると前記領域式が示す領域外へのアクセスとなるバッファオーバーフローが発生するバッファオーバーフロー条件を、前記指数式と前記サイズ式とを用いて算出する条件算出ステップと、
前記領域アクセス式を有するユニット内で前記バッファオーバーフロー条件を前記ユニット内の代入命令に基づき遡及させる第１の遡及ステップと、
上流のユニットから前記領域アクセス式を有する前記ユニットへの遷移のために前記分岐条件が存在するか否かを判断する第１の判断ステップと、
（Ａ−１）前記分岐条件が存在する場合は、前記バッファオーバーフロー条件と前記分岐条件とを比較する比較ステップと、
（Ａ−２）比較の結果、前記バッファオーバーフロー条件と前記分岐条件とが集合論的に重複する場合は、前記重複部分を新たなバッファオーバーフロー条件とし、新たな前記バッファオーバーフロー条件を前記上流のユニット内で前記上流のユニット内の代入命令に基づき遡及させる第２の遡及ステップと、
（Ａ−３）比較の結果、前記バッファオーバーフロー条件と前記分岐条件とが矛盾する場合は、前記上流のユニットから前記領域アクセス式を含むユニットへユニットが遷移した場合前記バッファオーバーフローは発生しない旨の判断を行う第２の判断ステップと、
（Ｂ−１）前記分岐条件が存在しない場合は、前記バッファオーバーフロー条件を前記上流のユニット内で前記上流のユニット内の代入命令に基づき遡及させる第３の遡及ステップと、
をコンピュータに実行させるバッファオーバーフロー脆弱性検出プログラム。
【請求項６】
前記第３の遡及ステップ又は前記第２の遡及ステップは、
さらなる上流のユニットから前記上流のユニットへの遷移のために分岐条件が存在するか否かを判断する第３の判断ステップと、
前記分岐条件が存在する場合は、前記バッファオーバーフロー条件と前記分岐条件とを比較するさらなる比較ステップと、
比較の結果、前記バッファオーバーフロー条件と前記分岐条件とが集合論的に重複する場合は、前記重複部分を新たなバッファオーバーフロー条件とし、新たな前記バッファオーバーフロー条件を前記さらなる上流のユニット内で前記さらなる上流のユニット内の代入命令に基づき遡及させる第４の遡及ステップと、
比較の結果、前記バッファオーバーフロー条件と前記分岐条件とが矛盾する場合は、前記さらなる上流のユニットから前記上流のユニットへユニットが遷移した場合、前記バッファオーバーフローは発生しない旨の判断する第４の判断ステップと、
前記分岐条件が存在しない場合は、前記バッファオーバーフロー条件を前記さらなる上流のユニット内で前記さらなる上流のユニット内の代入命令に基づき遡及させる第５の遡及ステップと、
前記判断ステップによって前記バッファオーバーフローは発生しない旨の判断がされない間、前記第３の判断ステップ、前記さらなる比較ステップ、前記第４及び第５の遡及ステップを繰り返し行う繰り返しステップと、
を備えたことを特徴とする請求項５に記載のプログラム。
【請求項７】
前記第３の遡及ステップ又は前記第２の遡及ステップは、遡及の結果を、ネストした条件付き式であるＮＣＥとして出力することを特徴とする請求項５又は６に記載のプログラム。
【請求項８】
解析対象となるプログラムから、予め確保された領域を示す領域式と、前記領域式が示す領域においてアクセスする位置を指定する指数式とを含む領域アクセス式を検出する領域アクセス式検出ステップと、
前記領域式が示す領域のサイズ式を検出する領域サイズ検出ステップと、
前記領域アクセス式を含む命令を実行すると前記領域式が示す領域外へのアクセスとなるバッファオーバーフローが発生するバッファオーバーフロー条件を、前記指数式と前記サイズ式とを用いて算出する条件算出ステップと、
前記プログラムの上流側に配置された命令から前記領域アクセス式を含む命令へ至るまでの命令の実行経路を特定し、前記実行経路上に配置された代入命令に基づき前記バッファオーバーフロー条件を前記実行経路の上流へ向けて遡及させる遡及ステップと、
を備えたバッファオーバーフロー脆弱性検出方法。
【請求項９】
前記遡及ステップは、前記実行経路上に分岐条件命令が含まれる場合は、前記実行経路に対応する分岐条件と、前記バッファオーバーフロー条件とを比較し、前記分岐条件と前記バッファオーバーフロー条件とが集合論的に重複する場合は、重複部分を新たなバッファオーバーフロー条件として遡及を続けることを特徴とする請求項８に記載の方法。
【請求項１０】
前記遡及ステップは、前記実行経路上に分岐条件命令が含まれる場合は、前記実行経路に対応する分岐条件と、前記バッファオーバーフロー条件とを比較し、前記分岐条件と前記バッファオーバーフロー条件とが矛盾する場合は、前記実行経路に沿って命令を実行した場合前記バッファオーバーフローは発生しない旨を判断することを特徴とする請求項８又は９に記載の方法。
【請求項１１】
ソースプログラムを字句解析及び構文解析する解析ステップと、
前記解析ステップによる解析結果に基づいて、
任意個数の宣言コードを冒頭に含み、任意個数の代入命令を中間に含み、多くとも１つの条件分岐命令を末尾に含み、実行は冒頭から始まり末尾まで直列実行されるユニット、が複数集まって作るユニット遷移グラフで、プログラムの実行はユニット間の遷移とユニット内の前記直列実行として表されるユニット遷移グラフであって、前記条件分岐命令を含むユニットから次のユニットへの遷移は、前記条件分岐命令の分岐条件に応じて決定されるユニット遷移グラフを生成するユニット遷移グラフ生成ステップと、
確保された領域を示す領域式と、前記領域においてアクセスする位置を指定する指数式とを含む領域アクセス式を前記ユニットから検出する領域アクセス式検出ステップと、
前記領域式が示す領域のサイズ式を検出する領域サイズ検出ステップと、
前記領域アクセス式を含む命令を実行すると前記領域式が示す領域外へのアクセスとなるバッファオーバーフローが発生するバッファオーバーフロー条件を、前記指数式と前記サイズ式とを用いて算出する条件算出ステップと、
前記領域アクセス式を有するユニット内で前記バッファオーバーフロー条件を前記ユニット内の代入命令に基づき遡及させる第１の遡及ステップと、
上流のユニットから前記領域アクセス式を有する前記ユニットへの遷移のために前記分岐条件が存在するか否かを判断する第１の判断ステップと、
（Ａ−１）前記分岐条件が存在する場合は、前記バッファオーバーフロー条件と前記分岐条件とを比較する比較ステップと、
（Ａ−２）比較の結果、前記バッファオーバーフロー条件と前記分岐条件とが集合論的に重複する場合は、前記重複部分を新たなバッファオーバーフロー条件とし、新たな前記バッファオーバーフロー条件を前記上流のユニット内で前記上流のユニット内の代入命令に基づき遡及させる第２の遡及ステップと、
（Ａ−３）比較の結果、前記バッファオーバーフロー条件と前記分岐条件とが矛盾する場合は、前記上流のユニットから前記領域アクセス式を含むユニットへユニットが遷移した場合前記バッファオーバーフローは発生しない旨の判断を行う第２の判断ステップと、
（Ｂ−１）前記分岐条件が存在しない場合は、前記バッファオーバーフロー条件を前記上流のユニット内で前記上流のユニット内の代入命令に基づき遡及させる第３の遡及ステップと、  
を備えたバッファオーバーフロー脆弱性検出方法。
【発明の詳細な説明】
【技術分野】
【０００１】
本発明は、バッファオーバーフロー脆弱性を静的解析により検出するバッファオーバーフロー脆弱性検出プログラム及びバッファオーバーフロー脆弱性検出方法に関し、より詳細には例えばＣソースプログラムに含まれるバッファオーバーフロー脆弱性をＣソースプログラムの静的解析により検出するプログラム及び方法に関する。
【背景技術】
【０００２】
近年、ソフトウエアに潜在する脆弱性の中で、最も問題となっているのがバッファオーバーフローである。バッファオーバーフローが潜在するソフトウエアによる実行プロセスは、プロセスの正常な動作が阻害されたり、最悪の場合、プロセス乗っ取りを攻撃者に許してしまう等、その被害は深刻である。特にＣプログラムは、Java（登録商標）プログラム等と異なり安全性に対する設計が足りない所が多く、危険な既存プログラムのストックが膨大なものに登るうえ、今後とも主要な言語の１つとして想定され多数の危険な新規プログラムが作成される可能性が高いため、この問題は大きい。
【０００３】
プログラムからバッファーオーバーを検出する方法として、プログラムの実行時においてバッファオーバーフローを検出する動的検出方法がある。しかし、この動的検出方法は、実際に発現したバッファオーバーフローのみ検出するものであるため、網羅的・体系的にバッファオーバーフローの発生し得る箇所及び発生条件を検出できない。また、この方法では、プログラムの実行速度が大きく低下するため、配布プログラムに動的検出のコードを埋め込むことは非現実的である。
【０００４】
一方、ソースプログラム中にプログラマがコメントを挿入等して、このコメントを利用して静的解析によりバッファオーバーフローを検出する方法もある。しかし、ソースプログラム中にコメントを挿入すること等はプログラマに多大の負荷をかけ、特に大規模なプログラムの場合にはその負荷は無視できないほど莫大である。
【特許文献１】特開２００４−１７１０６４公報
【発明の開示】
【発明が解決しようとする課題】
【０００５】
本発明は、上記問題点に鑑みてなされたものであり、その目的は、プログラマに一切負担をかけずに、検出漏れなく、少ない誤検出で、バッファオーバーフロー脆弱性を検出できるバッファオーバーフロー脆弱性検出プログラム及びバッファオーバーフロー脆弱性検出方法を提供することにある。
【課題を解決するための手段】
【０００６】
本発明の第１のバッファオーバーフロー脆弱性検出プログラムは、解析対象となるプログラムから、確保された領域を示す領域式と、前記領域式が示す領域においてアクセスする位置を指定する指数式とを含む領域アクセス式を検出する領域アクセス式検出ステップと、前記領域式が示す領域のサイズ式を検出する領域サイズ検出ステップと、前記領域アクセス式を含む命令を実行すると前記領域式が示す領域外へのアクセスとなるバッファオーバーフローが発生するバッファオーバーフロー条件を、前記指数式と前記サイズ式とを用いて算出する条件算出ステップと、前記プログラムの上流側に配置された命令から前記領域アクセス式を含む命令へ至るまでの命令の実行経路を特定し、前記実行経路上に配置された代入命令に基づき前記バッファオーバーフロー条件を前記実行経路の上流へ向けて遡及させ、前記バッファオーバーフロー条件の上流での表現を求める遡及ステップと、をコンピュータに実行させる。
【０００７】
前記遡及ステップは、前記実行経路上に分岐条件命令が含まれる場合は、前記実行経路に対応する分岐条件と、前記バッファオーバーフロー条件とを比較し、前記分岐条件と前記バッファオーバーフロー条件とが集合論的に重複する場合は、重複部分に基づき新たなバッファオーバーフロー条件を生成し遡及を続けることを特徴とする。
【０００８】
前記遡及ステップは、前記実行経路上に分岐条件命令が含まれる場合は、前記実行経路に対応する分岐条件と、前記バッファオーバーフロー条件とを比較し、前記分岐条件と前記バッファオーバーフロー条件とが矛盾する場合は、前記実行経路に沿って命令を実行した場合前記バッファオーバーフローは発生しない旨を判断することを特徴とする。
【０００９】
前記遡及ステップは、前記領域アクセス式を含む命令へ至る実行経路が複数存在する場合は各実行経路についてそれぞれ前記バッファオーバーフロー条件を遡及させることを特徴とする。
【００１０】
本発明の第２のバッファオーバーフロー脆弱性検出プログラムは、ソースプログラムを字句解析及び構文解析する解析ステップと、前記解析ステップによる解析結果に基づいて、任意個数の宣言コードを冒頭に含み、任意個数の代入命令を中間に含み、多くとも１つの条件分岐命令を末尾に含み、実行は冒頭から始まり末尾まで直列実行されるユニット、が複数集まって作るユニット遷移グラフで、プログラムの実行はユニット間の遷移とユニット内の前記直列実行として表されるユニット遷移グラフであって、前記条件分岐命令を含むユニットから次のユニットへの遷移は、前記条件分岐命令の分岐条件に応じて決定されるユニット遷移グラフを生成するユニット遷移グラフ生成ステップと、確保された領域を示す領域式と、前記領域においてアクセスする位置を指定する指数式とを含む領域アクセス式を前記ユニットから検出する領域アクセス式検出ステップと、前記領域式が示す領域のサイズ式を検出する領域サイズ検出ステップと、前記領域アクセス式を含む命令を実行すると前記領域式が示す領域外へのアクセスとなるバッファオーバーフローが発生するバッファオーバーフロー条件を、前記指数式と前記サイズ式とを用いて算出する条件算出ステップと、前記領域アクセス式を有するユニット内で前記バッファオーバーフロー条件を前記ユニット内の代入命令に基づき遡及させる第１の遡及ステップと、上流のユニットから前記領域アクセス式を有する前記ユニットへの遷移のために前記分岐条件が存在するか否かを判断する第１の判断ステップと、（Ａ−１）前記分岐条件が存在する場合は、前記バッファオーバーフロー条件と前記分岐条件とを比較する比較ステップと、  （Ａ−２）比較の結果、前記バッファオーバーフロー条件と前記分岐条件とが集合論的に重複する場合は、前記重複部分を新たなバッファオーバーフロー条件とし、新たな前記バッファオーバーフロー条件を前記上流のユニット内で前記上流のユニット内の代入命令に基づき遡及させる第２の遡及ステップと、（Ａ−３）比較の結果、前記バッファオーバーフロー条件と前記分岐条件とが矛盾する場合は、前記上流のユニットから前記領域アクセス式を含むユニットへユニットが遷移した場合前記バッファオーバーフローは発生しない旨の判断を行う第２の判断ステップと、（Ｂ−１）前記分岐条件が存在しない場合は、前記バッファオーバーフロー条件を前記上流のユニット内で前記上流のユニット内の代入命令に基づき遡及させる第３の遡及ステップと、をコンピュータに実行させる。
【００１１】
前記第３の遡及ステップ又は前記第２の遡及ステップは、さらなる上流のユニットから前記上流のユニットへの遷移のために分岐条件が存在するか否かを判断する第３の判断ステップと、前記分岐条件が存在する場合は、前記バッファオーバーフロー条件と前記分岐条件とを比較するさらなる比較ステップと、比較の結果、前記バッファオーバーフロー条件と前記分岐条件とが集合論的に重複する場合は、前記重複部分を新たなバッファオーバーフロー条件とし、新たな前記バッファオーバーフロー条件を前記さらなる上流のユニット内で前記さらなる上流のユニット内の代入命令に基づき遡及させる第４の遡及ステップと、比較の結果、前記バッファオーバーフロー条件と前記分岐条件とが矛盾する場合は、前記さらなる上流のユニットから前記上流のユニットへユニットが遷移した場合、前記バッファオーバーフローは発生しない旨の判断する第４の判断ステップと、前記分岐条件が存在しない場合は、前記バッファオーバーフロー条件を前記さらなる上流のユニット内で前記さらなる上流のユニット内の代入命令に基づき遡及させる第５の遡及ステップと、前記判断ステップによって前記バッファオーバーフローは発生しない旨の判断がされない間、前記第３の判断ステップ、前記さらなる比較ステップ、前記第４及び第５の遡及ステップを繰り返し行う繰り返しステップと、を備える。
【００１２】
前記第３の遡及ステップ又は前記第２の遡及ステップは、遡及の結果を、ネストした条件付き式であるＮＣＥとして出力することを特徴とする。
【００１３】
本発明の第１のバッファオーバーフロー脆弱性検出方法は、解析対象となるプログラムから、確保された領域を示す領域式と、前記領域式が示す領域においてアクセスする位置を指定する指数式とを含む領域アクセス式を検出する領域アクセス式検出ステップと、前記領域式が示す領域のサイズ式を検出する領域サイズ検出ステップと、前記領域アクセス式を含む命令を実行すると前記領域式が示す領域外へのアクセスとなるバッファオーバーフローが発生するバッファオーバーフロー条件を、前記指数式と前記サイズ式とを用いて算出する条件算出ステップと、前記プログラムの上流側に配置された命令から前記領域アクセス式を含む命令へ至るまでの命令の実行経路を特定し、前記実行経路上に配置された代入命令に基づき前記バッファオーバーフロー条件を前記実行経路の上流へ向けて遡及させ、前記バッファオーバーフロー条件の上流での表現を求める遡及ステップと、を備える。
【００１４】
前記遡及ステップは、前記実行経路上に分岐条件命令が含まれる場合は、前記実行経路に対応する分岐条件と、前記バッファオーバーフロー条件とを比較し、前記分岐条件と前記バッファオーバーフロー条件とが集合論的に重複する場合は、重複部分を新たなバッファオーバーフロー条件として遡及を続けることを特徴とする。
【００１５】
前記遡及ステップは、前記実行経路上に分岐条件命令が含まれる場合は、前記実行経路に対応する分岐条件と、前記バッファオーバーフロー条件とを比較し、前記分岐条件と前記バッファオーバーフロー条件とが矛盾する場合は、前記実行経路に沿って命令を実行した場合前記バッファオーバーフローは発生しない旨を判断することを特徴とする。
【００１６】
本発明の第２のバッファオーバーフロー脆弱性検出方法は、ソースプログラムを字句解析及び構文解析する解析ステップと、前記解析ステップによる解析結果に基づいて、任意個数の宣言コードを冒頭に含み、任意個数の代入命令を中間に含み、多くとも１つの条件分岐命令を末尾に含み、実行は冒頭から始まり末尾まで直列実行されるユニット、が複数集まって作るユニット遷移グラフで、プログラムの実行はユニット間の遷移とユニット内の前記直列実行として表されるユニット遷移グラフであって、前記条件分岐命令を含むユニットから次のユニットへの遷移は、前記条件分岐命令の分岐条件に応じて決定されるユニット遷移グラフを生成するユニット遷移グラフ生成ステップと、確保された領域を示す領域式と、前記領域においてアクセスする位置を指定する指数式とを含む領域アクセス式を前記ユニットから検出する領域アクセス式検出ステップと、前記領域式が示す領域のサイズ式を検出する領域サイズ検出ステップと、前記領域アクセス式を含む命令を実行すると前記領域式が示す領域外へのアクセスとなるバッファオーバーフローが発生するバッファオーバーフロー条件を、前記指数式と前記サイズ式とを用いて算出する条件算出ステップと、前記領域アクセス式を有するユニット内で前記バッファオーバーフロー条件を前記ユニット内の代入命令に基づき遡及させる第１の遡及ステップと、上流のユニットから前記領域アクセス式を有する前記ユニットへの遷移のために前記分岐条件が存在するか否かを判断する第１の判断ステップと、（Ａ−１）前記分岐条件が存在する場合は、前記バッファオーバーフロー条件と前記分岐条件とを比較する比較ステップと、  （Ａ−２）比較の結果、前記バッファオーバーフロー条件と前記分岐条件とが集合論的に重複する場合は、前記重複部分を新たなバッファオーバーフロー条件とし、新たな前記バッファオーバーフロー条件を前記上流のユニット内で前記上流のユニット内の代入命令に基づき遡及させる第２の遡及ステップと、（Ａ−３）比較の結果、前記バッファオーバーフロー条件と前記分岐条件とが矛盾する場合は、前記上流のユニットから前記領域アクセス式を含むユニットへユニットが遷移した場合前記バッファオーバーフローは発生しない旨の判断を行う第２の判断ステップと、（Ｂ−１）前記分岐条件が存在しない場合は、前記バッファオーバーフロー条件を前記上流のユニット内で前記上流のユニット内の代入命令に基づき遡及させる第３の遡及ステップと、を備える。
【発明の効果】
【００１７】
本発明により、プログラマに一切負担をかけずに、検出漏れなく、少ない誤り検出で、バッファオーバーフロー脆弱性を検出できる。
【発明を実施するための最良の形態】
【００１８】
先ず、本発明の実施の形態において用いるバッファオーバーフローなる用語について説明する。
【００１９】
一般的に「バッファオーバーフロー」という言葉が使われる場合、その意味は2種類の意味のどちらかで使われることが多い。片方は、最も広い意味でのバッファオーバーフローある。例えばバッファ領域への書き込みで考えれば、文字通り、バッファからデータが溢れるという現象である。もう一つは、ソフトウエア実行時にメモリ上に現れるデータ構造の中にスタックと呼ばれるものがあり、そのスタックの上にはソフトウエア実行制御に関わる重要なデータと通常のデータが並んで存在するが、通常データへの書き込みが重要なデータへの書き込みになってしまう現象である。これを攻撃者がうまく利用して、ソフトウエアの実行を乗っ取り、攻撃者の意図するコードを実行する攻撃をスタックスマッシングと呼ぶ。ここでは、前者の最も広い意味での現象を「バッファオーバーフロー」、後者のスタックスマッシングを許す現象を「スタックバッファオーバーフロー」と呼ぶことにする。後者は前者の一部である。すなわち、前者として発現した現象の一部が後者にもなり得る。
【００２０】
前者の最も広い意味でのバッファオーバーフローをより明確に定義すると、「ある領域への参照・書込みを意図した命令が、その領域の外への参照・書込みになる現象」ということになる。例えば、次のようなプログラムがあるとする。
【００２１】
Char* buf = malloc(size);
…
buf[a]=b;
…
mallocで確保された領域bufは、配列としてその領域にアクセスする場合、指数は0〜size-1の間になければならない。上の例でaが0<=a<=size-1であれば、バッファオーバーフローにはならないが、その範囲外に指数aがくる時はバッファオーバーフローとなる。
【００２２】
以下特に断らない限り、バッファオーバーフローというときはこの最も広い意味でのバッファオーバーフローを意味するものとする。このバッファオーバーフローを引き起こし得るプログラムの構造をバッファオーバーフロー脆弱性と呼ぶことにする。
【００２３】
バッファオーバーフロー脆弱性を含むソフトウエアを実行すると、次のような影響、あるいは被害が考えられる。
（１）ソフトウエアが異常動作に陥る。
（２）プログラマの意図しないコードが実行される可能性がある。
（３）攻撃者が任意のコードを実行するような乗っ取り攻撃を受ける可能性がある。
【００２４】
バッファオーバーフロー脆弱性は１種のバグである。通常のバグはその多くにおいて影響が（１）に留まるのに対して、バッファオーバーフローは（２）や（３）という影響があるのが特徴である深刻なバグである。
【００２５】
バッファオーバーフローを、その影響の深刻さに関してより細かくクラス分けしたとすると、最も影響の深刻なクラスとなるのが、前述したスタックバッファオーバーフローである。上述したようにこのスタックバッファオーバーフローも、最も広い意味でのバッファーバーフローに含まれる。スタックバッファオーバーフロー脆弱性の検出については、本発明者他の出願に係る特開２００４−１７１０６４公報（特願２００２−３３２８０２号）にて既に示した。
【００２６】
しかし、この特開２００４−１７１０６４公報に示す技術で検出可能なのはスタックバッファオーバーフロー脆弱性のみである。本実施の形態が検出対象とする脆弱性は、上述からも理解されるように、「ある領域への参照・書込みを意図した命令が、その領域の外への参照・書込みになること」の原因となる脆弱性、という最も広範な意味でのバッファオーバーフロー脆弱性である。
【００２７】
以下では、この最も広い意味でのバッファオーバーフロー脆弱性の検出手法について詳細に説明する。
【００２８】
図１は、本発明の実施の形態に従ったバッファオーバーフロー脆弱性検出プログラム及び方法による処理ステップを説明するフローチャートである。
【００２９】
まず、プログラマ等により作成されたＣソースプログラムを入力する（ステップＳ１１）。このＣソースプログラムにはマクロやインクルードファイルの設定がされている。
【００３０】
次に、Ｃソースプログラムのコンパイルに先立って、マクロ展開や、インクルードファイルのインクルードを行うプリプロセスと呼ばれる操作を解析対象のＣソースプログラムに施す（ステップＳ１２）。尚、プリプロセス後のＣソースプログラムも、Ｃ言語の文法に従ったＣソースプログラムである。
【００３１】
次に、プリプロセス後のＣソースプログラムの字句を解析し（字句解析）、解析結果に基づいて言語の構文規則を解析（構文解析）する（ステップＳ１３）。
【００３２】
ここで、字句解析及び構文解析並びに以降に説明する本実施の形態の説明の理解に必要な概念についていくつか説明する。
【００３３】
まず、文について説明する。C言語の文法規則における文とここで言う文とは同じである。すなわち、文はC言語の文法規則に従って、再帰的に定義されている。その要諦は、関数は一つの文または、複文であり、複文は文の並びとして構成される。文は一つの式から構成されることもあり、複数の文と予約語から構成されることもある。ある文Aを構成する単独あるいは複数の文をAの下位文と呼ぶ。以上について具体例を用いて説明する。
【００３４】
図２は、あるプログラム例に対する文の構造を示す。
【００３５】
関数proc全体が一つの複文を成し、複文は４つの下位文から成る。このうち、３番目以外の文は式から構成される文であり、３番目のif-then-else文は、”if”、”then”、”else”という３つの予約語と２つの下位文から構成される。これら２つの下位文はそれぞれ、式から構成される。尚、式から構成される文を式文と呼ぶ。
【００３６】
次に、式という概念について説明する。C言語の文法規則における式とここで言う式とは、後述のNCE(Nested Conditioned Expression)を除いて、同じである。すなわち、式はC言語の文法規則に従って、再帰的に定義されている。式は、変数や定数や演算子などが成す木構造である。その部分木それぞれも一つの式である。また、変数や定数も一つの式である。以上について具体例を用いて説明する。
【００３７】
図３は、式の例を示す。
【００３８】
プログラム例は図２と同じである。プログラム例における各式の構造が図の右側に示されており、それぞれ木構造を有している。例えば、c=2*aは代入式という式であり、その左辺は変数cという式（部分木）であり、右辺の2*aも式（部分木）であり、その両辺、2とaもそれぞれ式（部分木）である。また、buf[c]は配列式であり、それはbufという式とcという式から構成される。尚、Ｃ言語の３項演算子による式はNCEの一種であるが、本発明におけるＮＣＥは３項演算子による式以外の場合もある。
【００３９】
図１に戻り、ステップＳ１４において、字句解析・構文解析による解析結果を用いて、型決定処理を行う。Ｃ言語では全ての式に型付けが可能であることが文法規則として定められ、この型決定処理では、プリプロセス後のソースプログラムに含まれる全ての式について型を決定する。型としては、例えばint型、char型、ポインタ型等がある。
【００４０】
次に、プログラムに含まれる全ての代入式を、単純代入演算子（＝）を用いた代入式に変換する（ステップＳ１５）。これを代入式の正規化処理と称する。より詳細には以下の通りである。
【００４１】
式の１種として代入式がある。代入式の場合、前述の木構造（図３参照）のトップは代入演算子になる。代入演算子について、Ｃ言語には、+=や++といった多様な代入演算子があるが、それらは全て、単純代入演算子(=)と算術演算子、単純代入演算子とシフト演算子、単純代入演算子とbit演算子の組み合わせと等価である。また、代入演算子以外にはプリミティブな代入を実現するものは無い。よって、代入式は、それを等価変換することで、最終的には単純代入演算子を木構造のトップとする式に帰着できる。すなわち、全ての代入式は単純代入演算子による代入式に変換可能である。なお、代入式は１つで１ワードのみ代入を行う。
【００４２】
次に、代入式の正規化処理後のプログラムを用いてユニット遷移グラフの生成を行う（ステップＳ１６）。以下これについて詳細に説明する。
【００４３】
プログラムにおいて、一つの代入が行われる部分は文法上「式」になる。宣言の中に代入(初期化等)が入っていることがあるが、これは本質的には、純宣言と代入に分けられる(プログラムを等価変換することが可能)。例えばint a=100は、int a及びa=100と等価である。制御に関しても同様である。例えばif((a=b)>c)は、a=b及びif(a>c)と等価である。従って、プログラムは純宣言と、純制御と、代入部により表すことができる。
【００４４】
ここで、代入部とは、ある代入が行われた直後から次の代入が行われるまでの直列に実行が行われる部分を言うこととする。従って、一つの代入部について見ると、その末端は代入式であり、末端より前には関数呼び出し等が含まれ得るが、代入式は含まれない。つまり、一つの代入部では一つの代入しか行われない。
【００４５】
制御に関しては、条件判定をして成立／不成立による分岐を行うための文（例えばfor、while、if-then-else、switch：switchはif-then-elseの並び）と、条件判定を含まないラベル文とgoto文（return、break、continue文等もあるが実質的にgoto文と等価である）がある。
【００４６】
よって、プログラムは純宣言と条件判定(分岐)と代入部により表すことができる。
【００４７】
ここでユニットをいうものを定義する。ユニットは、（１）冒頭における任意個数の宣言、（２）任意個数の代入、（３）末尾に高々1個の条件判定による２分岐、（４）実行は必ず冒頭から末尾まで直列に行われ、途中に制御の流入が無い、という特徴を有するものとする。従って、プログラムあるいは関数の実行はユニット内の直列実行とユニット間の実行遷移という単純な構成で表現可能である。プログラムあるいは関数をユニットの遷移として表したものをユニット遷移グラフと称する。図４にユニット遷移グラフ例を示す。図４において点線で囲まれた部分がユニットである。本ステップＳ１６では、上述したように、このようなユニット遷移グラフを、正規化後のプログラムを用いて生成する。図４から理解されるように、ユニットに流入する制御(図４においてユニット先頭で代入部に入る矢印)は少なくとも１本、ユニットから流出する制御（図４においてユニット末端で条件判定から出る矢印）は０本か1本か２本である。
【００４８】
図５は、図２や図３で挙げたプログラム例に対して生成されたユニット遷移グラフを示す。
【００４９】
ユニットu0の末尾で一つの条件判定(c<3か否か)を行い、真偽に応じてユニットu1又はユニットu2へ遷移する。ユニットu1及びユニットu2からは、無条件でユニットu3へ遷移する。
【００５０】
図１に戻り、次に、このユニット遷移グラフを用いてバッファオーバーフロー候補を抽出する（ステップＳ１７）。バッファオーバーフロー候補としては例えばポインタ型式がある。以下これについて詳しく説明する。
【００５１】
配列とポインタは、宣言時のサイズを静的に指定するか、動的に指定するかを除いて、文法上は等しい存在である（実装の仕方は異なってくるが）。そこで、以下では、主としてポインタに関して話を進め、適宜配列について言及する。
【００５２】
Cの文法からポインタ型式の定義を抜き出して整理すると次のようになる。
例
ポインタ型式 : ポインタ型式 加減算演算子 整数型式    p+100+i
ポインタ型へのcast  ポインタ型式     (struct S *)p
ポインタ型変数                        p
&演算子 変数                          &i
【００５３】
Cの文法からポインタ型変数への代入式の定義を抜き出して整理すると次のようになる。
ポインタ型変数代入式 : ポインタ型変数 代入演算子 ポインタ型式     p2=p1+10
ポインタ型変数 代入演算子                  p1++
【００５４】
ポインタ型式が指す先へ値を代入する代入式の形を示すと次のようになる。
ポインタ型式が指す先への代入式 : *ポインタ型式 代入演算子 代入値
【００５５】
ここで、ポインタ型式は、例えば「ポインタ型式」及び「ポインタ型変数代入式」に示した再帰的定義からも分かるように、加減算演算子を節点とする２分木構造を成す。一例としてp+100+iの２分木構造を図６に示す。２分木構造における一つの端点（図６の例ではp）は代入先の領域を示すポインタ型式(領域式と呼ぶ)であり、残りの端点から構成される式（図６の例では100+i）は代入位置を示す整数型式(指数式と呼ぶ)である。この残りの端点は０個でもよい（上述の「ポインタ型式」における(struct S *)p、p、&iは領域式のみのポインタ型式に該当する）。
【００５６】
この２分木構造からも理解されるように、領域式はポインタ型式であり、指数式は整数型の式である。ポインタ型式には領域式のみから成るものと、領域式と指数式からなるものがある、ということになる。ポインタ型式における領域式と指数式の分別も局所的な解析で可能である。
【００５７】
ポインタ型式は、値が代入される側（代入式左辺）のみならず、値が参照される側（代入式右辺）にも出現する（「ポインタ型変数代入式」におけるp2=p1+10等参照）。この場合も、ポインタ型式における指数式と領域式の分類も局所的な解析で可能である。値が代入される側にポインタ型式が現れる例と、値が参照される側にポインタ型式が現れる例を以下にさらにいくつか示す。
【００５８】
値が代入される側にポインタ型式が現れる例：*(p+100+i)=100、s[100+i]=100
値が参照される側にポインタ型式が現れる例: a[100] = b->d[c]
a[100] = b->d[c]について簡単に説明すると、左辺のポインタ型式aで示される領域の指数式100で示される位置へ代入(書き込み)が成される。代入される値は、b->dというポインタ型式が示す領域における指数式cで示される位置への参照で得られる値である。
【００５９】
以上のように、ポインタ型式は、領域式から構成されるものと、領域式と指数式とから構成されるものがある。領域式で示される領域のサイズ（宣言時や動的割当時に指定される）から、指数式に許される値は制限される。指数式がそこから逸脱した値を取ると、上述したように、最も広い意味でのバッファオーバーフローになる。本ステップＳ１７では、プログラムに含まれる全てのポインタ型式のうち、指数式を持つものをバッファオーバーフロー候補として抽出する。
【００６０】
図１に戻り、次に、抽出された各ポインタ型式（バッファオーバーフロー候補）に含まれる指数式及び領域式のうち少なくとも指数式について遡及処理を行う（ステップＳ１８）。以下この遡及処理について詳細に説明する。
【００６１】
上述したように、ユニットは末尾の条件判定及び冒頭の宣言を除いて、代入部の並びであり、途中には条件分岐は存在しない（図４参照）。従って、ユニット内の任意の位置におけるある変数は、代入式の並びを下から上へ辿っていくことにより、ユニット冒頭における形に表現可能である。このユニットの冒頭に向けて辿っていくことを遡及と呼ぶことにする。より一般的には、遡及は、代入式の並びを下から上に辿っていくことにより、変数又は後述するバッファオーバーフロー条件といった任意の式を別の形の式で表現することである。逆にいえば、遡及後の式に、代入式の並びを上から下へ従って適用していくと遡及前の式になる。
【００６２】
ここで、遡及は、
・左辺可能式と呼ぶ特殊な構造をもった式（これはＣの言語仕様によって、左辺値を持つ式として定義できる）（遡及の対象としている式であるか否かは問わない）が、ある代入式の右辺に現れており、
・その左辺可能式がユニット中の代入式の並びの中でより上の代入式の左辺に出現するという場合に可能である。
【００６３】
左辺可能式としては、例えば、単独変数、配列要素、*（ポインタ型式）、構造体メンバ等がある。
【００６４】
図７（Ａ）〜（Ｅ）は、遡及処理の一例を説明する図である。
【００６５】
図７（Ａ）は、ユニット内に配置されたポインタ型式f[a]の指数式aについて遡及した結果を示す。aは同ユニット内の位置＠２ではb+cに遡及され、同ユニット内の位置＠１では、d+c+eに遡及される。
【００６６】
図７（Ｂ）は、ユニット内におけるある位置に配置されたポインタ型式c[a[b]]の指数式a[b]について遡及した結果を示す。a[b]は同ユニット内の位置＠１では、fに遡及される。
【００６７】
図７（Ｃ）は、ユニット内におけるある位置に配置されたポインタ型式c[a[b]]の指数式a[b]について遡及した結果を示す。a[b]は同ユニット内の位置＠１では、a[c+d]に遡及される。
【００６８】
図７（Ｄ）及び図７（Ｅ）に示す例４や例５は遡及の結果が場合によって異なることを示している。
【００６９】
すなわち、図７（Ｄ）では、ポインタ型式c[a[b]]における指数式a[b]は、もしe=c+dが成立する場合は、位置＠１においてfに遡及されるが、成立しない場合は、a[c+d]に遡及される。
【００７０】
同様に、図７（Ｅ）では、ポインタ型式c[a[b]]における指数式a[b]は、もしe=bが成立する場合は、位置＠１でfに遡及されるが、成立しない場合は、a[b]に遡及される。
【００７１】
図７（Ｄ）及び図７（Ｅ）に示す例のように、遡及結果は一般的には条件付き式で表現する必要がある。条件付き式は、条件式、条件式が真の場合の式及び条件式が偽の場合の式の３項による組からなる式である。
【００７２】
条件付き式も遡及の対象になる。例えば図７（Ｄ）に示す例４で、a[b]の遡及結果は図示の条件付き式により表現されるが、＠１を超えてさらに上へa[b]を遡及する場合は、この条件付き式を＠１から上へ遡及することになる。この場合、遡及は条件付き式を構成する３つの式それぞれについて行う。この遡及結果がまた、条件付式になる可能性もある。よって、遡及結果を表現する条件付き式はネストした条件付き式（例４，５参照）である必要がある。このネストした条件付き式をNCE(Nested Conditioned Expression)と呼ぶことにする。
【００７３】
ここで、本ステップＳ１８では、前述したステップＳ１７においてユニット内で見つかったポインタ型式（バッファオーバーフロー候補）を構成する指数式及び領域式の少なくとも指数式を遡及し、ユニット冒頭での表現に直す。
【００７４】
図８は、図５に示したユニット遷移グラフの各ユニットu0〜u3において、ポインタ型式buf[c]における指数式cを遡及した結果を示す。
【００７５】
指数式cは、ユニットu3の冒頭では、cに遡及され、u1の冒頭ではc-1に遡及され、u2の冒頭ではc+1に遡及され、u0の冒頭では2aに遡及される。
【００７６】
図１に戻り、次に、ユニット間でのリレー処理を行う（ステップＳ１９）。
【００７７】
このリレー処理は、着目する変数について、ユニット間を跨いで遡及を行うものである。
【００７８】
図９は、図８に示すユニット間のリレーを、指数式cについて行った結果を示す。リレー処理の結果はNCEになる。あるユニットＢの冒頭まで遡及された遡及後の式Ｅは、そのユニットの（ユニット遷移グラフ上で）上流にあるユニットＡの末尾へと遡及を引き継ぐ（ユニットＡの末尾に式Ｅがあると仮想し、そこからユニットＡ内で遡及を始める）ことで、ユニットＡの冒頭まで遡及ができる。このユニット間を跨ぐ遡及を実現するためのリレーを行う。ユニット内での遡及と、ユニット間でのリレーを交互に行うことによって、プログラム中の任意のユニットは、ユニットグラフを上流に辿れる限り、どこまでも遡及されることが可能である。
【００７９】
図９において、リレーの結果、指数式cは、ユニットu1の冒頭では、c-1に遡及され、ユニットu0の冒頭では2a-1に遡及される。同様に、指数式cは、ユニットu2の冒頭では、c+1に遡及され、ユニットu0の冒頭では2a+1に遡及される。つまり、ユニットがu0→u1→u3と遷移する場合は、指数式cは2a-1に遡及され、ユニットがu0→u2→u3と遷移する場合は、指数式cは2a+1に遡及される。
【００８０】
図１に戻り、次に、バッファオーバーフロー条件の同定並びにバッファオーバーフロー条件の精緻化及び削減化を行う（ステップＳ２０、Ｓ２１）。以下具体例として、図９を用いて、本ステップについて詳細に説明する。
【００８１】
まず、ユニットu3の冒頭においてbuf[c]にバッファオーバーフローが生じる条件（バッファオーバーフロー条件）を求める（バッファオーバーフロー条件の同定）。但し、bufで示される領域のサイズが関数の冒頭において「２」と宣言されていたとする。従って、buf[c]というポインタ型式のバッファオーバーフロー条件はc>=2である(c<0ももう一つのバッファオーバーフロー条件である)。この時点におけるバッファオーバーフロー条件は、buf[c]の位置における局所的なものであることに注意する。また、バッファオーバーフロー条件は式であることにも注意する。従って、バッファオーバーフロー条件には遡及とリレーが行える。
【００８２】
次に、ユニット内でのバッファオーバーフロー条件の遡及とユニットを跨いでバッファオーバーフロー条件のリレーを行う。上流ユニットが複数ある場合は、リレーはそれぞれの上流ユニットに対して行う。ユニットu3の上流には２つのユニットu1,u2が存在するためそれぞれのユニットu1,u2に対してリレーを行う。
【００８３】
まず、ユニットu1冒頭までバッファオーバーフロー条件を遡及させると遡及結果はc>=3となる。より詳細には、この遡及の際には、図９に示すリレー処理の結果を用いる。リレー処理の結果から、指数式cはユニットu1の冒頭においてc-1に遡及される。従って、バッファオーバーフロー条件は、c-1>=2すなわちc>=3に遡及される。
【００８４】
次に、ユニットu2冒頭までバッファオーバーフロー条件を遡及させると遡及結果はc>=1となる。すなわち、リレー処理の結果から、指数式cはユニットu2の冒頭においてc+1に遡及される。従ってバッファオーバーフロー条件は、c+1>=2すなわちc>=1に遡及される。
【００８５】
次に、各ユニットu1,u2に実行が遷移してくる条件と、各ユニットu1,u2の冒頭でのバッファオーバーフロー条件とを突き合わせる。前者が後者によって全否定されるならば、バッファオーバーフローは生起しない。一方、全否定されない場合は、バッファオーバーフロー条件及び遷移条件の集合論的な重複部分を新たなバッファオーバーフロー条件として生成し、新たなバッファオーバーフロー条件に基づき遡及を続行する。より詳細には以下の通りである。
【００８６】
まず、ユニットu0からユニットu1への遷移条件（c<3）は、ユニットU1冒頭でのバッファオーバーフロー条件（c>=3）を全否定するため、すなわち両者は矛盾するため、ユニットu0→ユニットu1→ユニットu3という実行順序を辿る場合は、ユニットu3のbuf[c]でバッファオーバーフローは生起し得ない。従って、c>=3を、最終的なバッファオーバーフロー条件から除外する（バッファオーバーフロー条件の削減化）。
【００８７】
一方、ユニットU0からユニットu2への遷移条件（c>=3）は、ユニットu2冒頭でのバッファオーバーフロー条件（c>=1）より厳しい(集合論的に言えば、部分集合)ため、遷移条件の方を新たなバッファオーバーフロー条件（c>=3）とする。つまり、バッファオーバーフロー条件が表す集合と遷移条件が表す集合との交わりを表す式を新たなバッファオーバーフロー条件とする。この結果、バッファオーバーフロー条件はより狭い範囲に絞り込まれる（バッファオーバーフロー条件の緻密化）。この新たな条件をユニットU0の冒頭まで遡及（リレー）させると2a>=3となり、これより上流のユニットは存在しないため遡及を終了する。即ち、予め与えられた終了条件を満たした場合は遡及を終了する。この結果、ユニットu0の冒頭、つまり関数冒頭で2a>=3という条件が満たされていれば、ユニットu3のbuf[c]でバッファオーバーフローが生起するというバッファオーバーフロー条件が得られる。一方で、ユニットu0のbuf[c]については、2a>=2という条件でバッファオーバーフローが生起する。
【００８８】
以上において、もしもユニットu1、u2の冒頭におけるバッファオーバーフロー条件のいずれもがユニットu0から各ユニットu1,u2への遷移条件によって全否定された場合は、対象としているバッファオーバーフロー候補ではバッファオーバーフローが生起し得えないため候補から除外する。
【００８９】
以上のステップＳ２０、Ｓ２１の説明では、関数の冒頭で、bufで示される領域のサイズが「２」と宣言されたが、bufで示される領域のサイズが宣言されていない場合はbufを遡及及びリレーすることによりサイズを求める。
【００９０】
例えば、
int* p = (int*)malloc(sizeof(int)*sizeP); //@1
int* q;
...
q = p;
...
q[b]=...
というプログラムの場合、ポインタ型式q[b]における領域式qは、そのサイズが直接宣言されていないため、領域式qを遡及することにより、@1で確保された領域だということ、すなわち、サイズを認識できる。このことを一般的な表現にすると次のようになる。領域式が示す領域には、配列のように宣言によってサイズが固定されているもの（Ｃ言語では静的確保される領域と呼ばれる）と、領域確保関数によって確保されサイズが実行時に決まるもの（同じく動的確保される領域と呼ばれる）がある。前者を静的領域、後者を動的領域と呼ぶことにする。静的領域は、それを示す領域式と宣言の対比で簡単に同定可能であり、従ってサイズも同定可能である。一方、動的領域は領域式を遡及およびリレーして、左辺が遡及後の領域式で右辺が領域確保関数という形の代入式である領域確保式まで辿り付くことで、初めてそのサイズを表す式であるサイズ式が分かる（サイズ式は領域確保関数の引数の一部）。従って、領域式が示す領域が静的領域でない場合は、それは動的領域であるか、後述する他領域式指示であり、領域式を遡及およびリレーする。そして領域確保式まで辿り付けば、そのサイズ式を求める。尚、静的領域のサイズを表す即値の式（例えばint a[100];という宣言における100）もあるので、これも動的領域の場合と同様にサイズ式と呼ぶことにする。
【００９１】
領域式はポインタ型式であるので、単一のポインタ型変数等、左辺式である場合がある。その場合、その領域式は他の領域式によって代入が成された結果である場合もある。上の領域式(今これをAとする)の遡及およびリレーで、他の静的領域の領域式Ｂにたどり着いた場合は、領域式Ａは、領域式Ｂと同じ領域を示すこととする。これを他領域式指示と呼ぶ。領域式Ｂを遡及及びリレーすることで領域式Ｂのサイズ式が求まる。
【００９２】
請求項における領域式が示す領域のサイズ式の検出は、（１）領域式と宣言との対比により検出すること、（２）遡及及びリレーにより領域確保式を検出すること、（３）他領域式指示の場合は他領域式が示す領域のサイズ式を（１）（２）により検出することを含む。
【００９３】
以上の説明で用いた例では、buf[c]のように[ ]の中が変数であったが、buf[2]のように[ ]の中が定数であれば、bufのサイズから、即時にバッファオーバーフローか否かが判定可能である。
【００９４】
図１に戻り、最終的な処理結果を出力する（ステップ２２）。
【００９５】
最終的な処理結果として、バッファオーバーフロー条件の精緻化及び削減化過程において除外されずに生き残ったバッファオーバーフロー候補について以下の情報を出力する。
（１）バッファオーバーフローが生起し得る個所である、領域式と指数式から構成されるポインタ型式（すなわちバッファオーバーフロー候補）（上記例ではユニットu3のbuf[c]）
（２）バッファオーバーフローが生起し得る、領域式が示す領域（上記例ではbufが確保されている宣言文or命令文。bufが配列として確保された領域なら例えばint buf[size];等、mallocで確保された領域なら、int* buf = (int*)malloc(sizeof(int)*sizeA);等）
（３）バッファオーバーフローが生起する条件（上記例では、ユニットu0:3≦2a、ユニットu2:c≧1、ユニットu3:c≧2等、ユニットごとに出力）
といった情報である。
【００９６】
以上に説明した本発明の実施の形態により得られる効果について述べると以下の通りである。
【００９７】
バッファオーバーフローを生起し得るプログラムの箇所について、その箇所で実際にバッファオーバーフローが生起する必要条件を同定できる。但し、本実施の形態により、プログラムを広域的に静的解析することにより、必要十分条件に近い条件を得られ、このことは、誤検出の割合を少なくする効果を実現する。誤警告が出るのは、例えば次のような場合である。
【００９８】
すなわち、本実施の形態では、プリプロセス後のソースプログラムを用いて解析を行っている。ヘッダーファイルが完全に揃っていない等の理由でプリプロセスが完全に行えない場合、解析が不十分になるところが出てくる場合がある。
【００９９】
以上のように同定されたバッファオーバーフロー条件を検討することによって、どういう仕組みでバッファオーバーフローが生起するか、裏を返せば、プログラムをどう修正すればバッファオーバーフローを起こさなくなるかが分かる。例えば、バッファオーバーフロー条件を条件式とするif文をバッファオーバーフロー条件箇所に埋め込むことでバッファオーバーフローの生起を防止できる。
【０１００】
以上の他、本実施の形態では、バッファオーバーフローが生起し得る全ての式を処理の対象とするため、バッファオーバーフローを生起し得るプログラムの箇所を漏らさず検出できる。また、プログラマにコメント追加等の不可を一切求めていないことは以上の記述より明らかである。
【図面の簡単な説明】
【０１０１】
【図１】本発明の実施の形態に従ったバッファオーバーフロー脆弱性検出プログラム及び方法による処理ステップを説明するフローチャートである。
【図２】あるプログラム例に対する文の構造を示す。
【図３】式の例を示す。
【図４】ユニット遷移グラフ例を示す。
【図５】図２や図３で挙げたプログラム例に対して生成されたユニット遷移グラフを示す。
【図６】p+100+iの２分木構造を示す。
【図７】遡及処理の一例を説明する図である。
【図８】図５に示したユニット遷移グラフの各ユニットu0〜u3において、ポインタ型式buf[c]における指数式cを遡及した結果を示す。
【図９】図８に示すユニット間のリレーを、指数式cについて行った結果を示す。
【符号の説明】
【０１０２】
Ｓ１１  ソースプログラム入力ステップ
Ｓ１２  プリプロセス実行ステップ
Ｓ１３  字句解析・構文解析ステップ
Ｓ１４  型決定処理ステップ
Ｓ１５  代入式の正規化ステップ
Ｓ１６  ユニット遷移グラフの生成ステップ
Ｓ１７  バッファオーバーフロー候補の抽出ステップ
Ｓ１８  遡及処理ステップ
Ｓ１９  リレー処理ステップ
Ｓ２０  バッファオーバーフロー条件の同定ステップ
Ｓ２１  バッファオーバーフロー条件の精緻化及び削減化
Ｓ２２  出力処理ステップ
【図１】
2006031363.tif 000003
【図２】
2006031363.tif 000004
【図３】
2006031363.tif 000005
【図４】
2006031363.tif 000006
【図５】
2006031363.tif 000007
【図６】
2006031363.tif 000008
【図７】
2006031363.tif 000009
【図８】
2006031363.tif 000010
【図９】
2006031363.tif 000011