(57)【要約】  【課題】  ブログラミング言語のプログラムが生成する文字列の妥当性を、該プログラムを実行せずに判定すること。  【解決手段】  文字列の宣言を含む、各変数の定義が唯一となるようなブログラミング言語のソースコードから、変数の間の制約を抽出して、Ｍ２Ｌで記述し、文字列の安全／非安全の記述をＭ２Ｌにより与え、与えられた変数の間の制約と、文字列の安全／非安全の記述により、Ｍ２Ｌソルバ上で、文字列の妥当性を判断するステップとを有する、プログラムが生成する文字列の妥当性を判定する方法が提供される。【選択図】  図２
2011013810.tif 000002
【特許請求の範囲】
【請求項１】
コンピュータの処理により、ブログラミング言語のプログラムが生成する文字列の妥当性を、該プログラムを実行せずに判定する方法であって、
前記コンピュータの処理により、文字列の宣言を含む、各変数の定義が唯一となるようなブログラミング言語のソースコードから、変数の間の制約を抽象化して、Ｍ２Ｌで記述し、記憶手段に保存するステップと、
前記コンピュータの処理により、前記変数の間の制約と、予め用意されて前記記憶手段に保存された文字列の安全／非安全のＭ２Ｌの記述により、Ｍ２Ｌソルバ上で、文字列の妥当性を判断するステップとを有する、
プログラムが生成する文字列の妥当性を判定する方法。
【請求項２】
前記各変数の定義が唯一となるようなブログラミング言語がＳＳＡ形式である、請求項１の方法。
【請求項３】
前記プログラミング言語がJavaである、請求項１の方法。
【請求項４】
コンピュータの処理により、ブログラミング言語のプログラムが生成する文字列の妥当性を、該プログラムを実行せずに判定する処理プログラムであって、
文字列の宣言を含む、文字列の宣言を含む、各変数の定義が唯一となるようなブログラミング言語のソースコードから、変数の間の制約を抽象化して、Ｍ２Ｌで記述し、記憶手段に保存するステップと、
前記変数の間の制約と、予め用意されて前記記憶手段に保存された文字列の安全／非安全のＭ２Ｌ記述により、Ｍ２Ｌソルバ上で、文字列の妥当性を判断するステップとを有する、
文字列の妥当性を判定する処理プログラム。
【請求項５】
前記各変数の定義が唯一となるようなブログラミング言語がＳＳＡ形式である、請求項４の処理プログラム。
【請求項６】
前記プログラミング言語がJavaである、請求項４の処理プログラム。
【請求項７】
コンピュータの処理により、ブログラミング言語のプログラムが生成する文字列の妥当性を、該プログラムを実行せずに判定するシステムであって、
記憶手段と、
前記コンピュータの処理により、文字列の宣言を含む、各変数の定義が唯一となるようなブログラミング言語のソースコードから、変数の間の制約を抽象化して、Ｍ２Ｌで記述し、前記記憶手段に保存する手段と、
前記コンピュータの処理により、文字列の安全／非安全の記述をＭ２Ｌにより用意して、前記記憶手段に保存する手段と、
前記コンピュータの処理により、前記与えられた変数の間の制約と、文字列の安全／非安全の記述を用いて、Ｍ２Ｌソルバの機能を利用して、文字列の妥当性を判断する手段とを有する、
プログラムが生成する文字列の妥当性を判定するシステム。
【請求項８】
前記各変数の定義が唯一となるようなブログラミング言語がＳＳＡ形式である、請求項７のシステム。
【請求項９】
前記プログラミング言語がJavaである、請求項７のシステム。
【発明の詳細な説明】
【技術分野】
【０００１】
この発明は、コンピュータ・プログラムのコードにおける文字列（ストリング）妥当性を判定する技術に関するものである。
【背景技術】
【０００２】
世の中でインターネットが隆盛するにつれて、セキュリティ上の危険性も増大してきた。その典型的な危険性として、クロスサイトスクリプティング（ＸＳＳ）がある。これは、アプリケーション・プログラムによって動的に生成されるウェブ・ページに、サイト間を横断して悪意のあるスクリプトを混入させることである。
【０００３】
他の危険性として、ＳＱＬインジェクションがある。これは、既存のＳＱＬ文に、別のＳＱＬ文を注入することによって、アプリケーションが想定しないＳＱＬ文を実行させることにより、データベースシステムを不正に操作するものである。
【０００４】
ＣＧＩプログラムで、ＸＳＳの危険性を検出するためには、例えば、print関数に、'<'という文字が渡されるかどうかを調べる必要がある。
【０００５】
特開２００７−５２６２５号公報は、検査対象のソースコードを構文解析手段により解析して解析木を構築するシステム開示する。そこで、脆弱性検出手段は解析木を辿り動的仮引数間遷移ＤＢを作製する。これと仮引数間遷移ＤＢから検査対象のソースコードにおける外部入力の遷移を追跡し、外部入力をパラメータとして使用すると脆弱な関数を登録した脆弱性データベースの登録内容に合致する箇所を、脆弱性を有する箇所として警告する。
【０００６】
この公開公報に開示されている技法は、ソースコードの脆弱性を検査することに関するが、外部入力の遷移に関するもので、プログラムが生成する文字列の値に関与するものではない。
【０００７】
下記に掲げる非特許文献１、２及び３は、プログラムを実行しないで、実行時に生起する文字列の値を推論するための静的プログラム解析技術を開示する。典型的には、静的プログラム解析技術は、文法（正規文法または文脈自由文法）によって文字列の値を抽象し、推論した文字列の値を、予め用意した安全または非安全なパターンと比較することによって、セキュリティの脆弱性を検出するために使用される。
【０００８】
しかし、文法ベースのアプローチは、モジュール化が難しいという点で、制約がある。さらに、文法ベースのアプローチは、後ろ向き解析に使用したり、文字列のインデックスと文字列の値の間の関係を扱ったりするのが、困難である。
【０００９】
例えば、非特許文献２の文字列解析は、文脈自由文法の変形に依存している。すると、非特許文献２の文字列解析をモジュール化するには、そのような変形の合成を計算する必要があり、非特許文献２の文字列解析を後ろ向き解析に使用するには、そのような変形を逆転する必要がある。
【００１０】
このように、モジュール化された解析と、後ろ向き解析には、文字列解析の推論フェーズで追加のアルゴリズムが必要である。
【００１１】
ところで、単項２階論理（Ｍ２Ｌ）によって、文字列上の特性を扱うというアイデアも考えられる。Ｍ２Ｌによれば、合成は、なんら特別なアルゴリズムを使用することなく、単なる論理演算（例えば、∧）によって行うことができる。Ｍ２Ｌの式を解くためのＢＤＤベースのアルゴリズムが、組合せの爆発の問題を解消することに貢献する。
【００１２】
Ｍ２Ｌを解くためのプログラムの例として、MONAがあり、http://www.brics.dk/mona/からプログラムを入手することができる。
【００１３】
特に、http://www.brics.dk/mona/publications.htmlの６．６章には、正規表現のためのエンコーディング方法が記述されている。
【００１４】
非特許文献４に記述されている技術は、プログラム中の文字列演算が、ＭＳＯ（単項２階論理）で定義可能な文字列変換によって定義または近似可能であるなら、文字列の結合や反転の問題を解決し得るものである。しかし、静的プログラム解析の観点からみると、この論文は、Ｍ２Ｌによってプログラムを抽象するためのアルゴリズムは何ら記述しない。
【００１５】
それ以外にも、非特許文献５に記述されている技術のように、Ｍ２Ｌを用いてプログラムを検証するための研究はある。
【００１６】
しかし、従来のどの研究や技術も、プログラムによって生成される文字列の値の検証に取り組むものではない。
【先行技術文献】
【特許文献】
【００１７】
【特許文献１】特開２００７−５２６２５号公報
【非特許文献】
【００１８】
【非特許文献１】Aske Simon Christensen, Anders Moller, and Michael I. Schwartzbach, "Precise Analysis of String Expressions", In SAS'03 Proceedings of International Static Analysis Symposium, volume 2695 of LNCS, page 1-18, Springer-Verlag 2003
【非特許文献２】Yasuhiko Minamide, Static approximation of dynamically generated Web pages, International World Wide Web Conference archive, Proceedings of the 14th international conference on World Wide Web table of contents, Pages: 432 - 441, 2005, ACM New York, NY, USA
【非特許文献３】Gary Wassermann, Zhendong Su, Sound and precise analysis of web applications for injection vulnerabilities, In PLDI'07 Proceedings of Programming Language Design and Implementation, 2007
【非特許文献４】Joost Engelfriet, Hendrik Jan Hoogeboom, MSO definable string transductions and two-way finite-state transducers, ACM Transactions on Computational Logic, Volume 2, Issue 2 (April 2001) Pages: 216 - 254
【非特許文献５】Anders Moller, Michael I. Schwartzbach, The pointer assertion logic engine, ACM SIGPLAN Volume 36 ,  Issue 5  (May 2001) Pages: 221 - 231
【発明の概要】
【発明が解決しようとする課題】
【００１９】
この発明の目的は、プログラムが生成する文字列の妥当性を、プログラムを実際に実行せずに効率的に判定する技法を提供することにある。
【課題を解決するための手段】
【００２０】
上記目的を達成するために、本願発明者は、単項２階論理（Ｍ２Ｌ）に基づく文字列解析技術に想到した。Ｍ２Ｌは、２階変数の使用によって正規言語を定義するに十分な表現力をもつ。
【００２１】
本願発明者は、この表現力を利用して、プログラム変数間の制約を記述し、組込み文字列演算を抽象した。これによれば、あらゆる組込み組込み文字列演算は、その入力値と出力値上の制約によってモデルされる。プログラム全体が一旦Ｍ２Ｌに変換されると、そのプログラムが、Ｍ２Ｌソルバを用いて、やはりＭ２Ｌで書かれた仕様を満足するかどうかが判定される。
【００２２】
本発明によれば先ず、位置の集合よって、文字列が表現される。この際、文字の順序に関する情報は失われない。２つの文字列の結合は、２つの位置集合Ｓ1とＳ2の和集合によってあらわされる。ここで、Ｓ1の全ての位置は、Ｓ2の全ての位置よりも下位にある。
【００２３】
次に、命令が、Ｍ２Ｌ述語宣言に変換される。その各々のＭ２Ｌ述語宣言は、起こりえる全ての文字列の性質(property)をあらわし、これらは、実行時に対応する変数に割り当てられることになる。
【００２４】
次に、非循環変数を終端記号と考えて、非循環変数に対応する終端記号からＭ２Ｌ述語への変換を通じて、変数の循環定義に関連する命令が、正規文法（または、正規表現）に変換される。
【００２５】
次に、入力文字列値と、出力文字列値の間の制約によって、組込み文字列関数の健全な抽象が定義される。その際、入力ストリングに対応するパラメータが、高階変数によって抽象され、高階変数の各々は、プログラムによって生成されたＭ２Ｌ述語によってインスタンス化される。
【００２６】
各文字列インデックスが文字列と文字列集合の対によってエンコードされてなる、文字列インデックスを扱う機能によって、解析手法が強化される。
【００２７】
さらに、追加のビットを使用することによって、ラベル付け機能で、解析手法が強化される。
【００２８】
さらに、条件を考慮した機能も使用することができ、これによって、解析手法が強化される。
【発明の効果】
【００２９】
以上のように、この発明によれば、プログラムのソートコードと、そのプログラムが実行時に生成する文字列の制約条件の両方を、Ｍ２Ｌで記述することによって、Ｍ２Ｌソルバを用いて、プログラムが生成する文字列の妥当性を、効率的に解くことができるという効果が得られる。
【図面の簡単な説明】
【００３０】
【図１】本発明を実施するためのハードウェア構成のブロック図である。
【図２】本発明の処理を行なう機能ブロック図を示す図である。
【図３】本発明の処理全体の概要フローチャートを示す図である。
【図４】述語生成器の処理のフローチャートを示す図である。
【発明を実施するための形態】
【００３１】
以下、図面に基づき、この発明の実施例を説明する。特に断わらない限り、同一の参照番号は、図面を通して、同一の対象を指すものとする。尚、以下で説明するのは、本発明の一実施形態であり、この発明を、この実施例で説明する内容に限定する意図はないことを理解されたい。
【００３２】
図１を参照すると、本発明の一実施例に係るシステム構成及び処理を実現するためのコンピュータ・ハードウェアのブロック図が示されている。図１において、システム・パス１０２には、ＣＰＵ１０４と、主記憶（ＲＡＭ）１０６と、ハードディスク・ドライブ（ＨＤＤ）１０８と、キーボード１１０と、マウス１１２と、ディスプレイ１１４が接続されている。ＣＰＵ１０４は、好適には、３２ビットまたは６４ビットのアーキテクチャに基づくものであり、例えば、インテル社のＰｅｎｔｉｕｍ（商標）  ４、Ｃｏｒｅ（商標）２  Ｄｕｏ、Ｘｅｏｎ（商標）、ＡＭＤ社のＡｔｈｌｏｎ（商標）などを使用することができる。主記憶１０６は、好適には、２ＧＢ以上の容量をもつものである。
【００３３】
ハードディスク・ドライブ１０８には、個々に図示しないが、オペレーティング・システムが、予め格納されている。オペレーティング・システムは、Ｌｉｎｕｘ（商標）、マイクロソフト社のＷｉｎｄｏｗｓ  ＸＰ（商標）、Ｗｉｎｄｏｗｓ（商標）２０００、アップルコンピュータのＭａｃ  ＯＳ（商標）などの、ＣＰＵ１０４に適合する任意のものでよい。
【００３４】
ハードディスク・ドライブ１０８にはまた、必要に応じて、Ｃ、Ｃ＋＋、Ｃ＃、Ｊａｖａ（商標）などのプログラム言語処理系も格納していてもよい。ハードディスク・ドライブ１０８にはさらに、プログラム言語処理系でコンパイルするためのソースコードを書くためのテキスト・エディタ、及び、Ｅｃｌｉｐｓｅ（商標）などの開発環境を含んでいてもよい。
【００３５】
ハードディスク・ドライブ１０８にはさらに、Ｍ２Ｌソルバである、MONAが格納されている。
MONAは、http://www.brics.dk/mona/download.htmlから入手可能である。
【００３６】
ハードディスク・ドライブ１０８にはさらに、Java(商標)ソースコードを、SSA形式に変換するツールが格納されている。
そのようなツールは例えば、http://wala.sourceforge.net/から入手可能である。チェックしようとするプログラミング言語のソースコードが、Java(商標)以外のＣ、Ｃ＋＋、Ｃ＃、その他の言語である場合でも、
【００３７】
キーボード１１０及びマウス１１２は、オペレーティング・システムまたは、ハードディスク・ドライブ１０８から主記憶１０６にロードされ、ディスプレイ１１４に表示されたプログラム（図示しない）を起動したり、文字を打ち込んだりするために使用される。
【００３８】
ディスプレイ１１４は、好適には、液晶ディスプレイであり、例えば、ＸＧＡ（１０２４×７６８の解像度）、またはＵＸＧＡ（１６００×１２００の解像度）などの任意の解像度のものを使用することができる。ディスプレイ１１４は、図示しないが、プログラムのチェック結果の表示などの目的に使用される。
【００３９】
次に、本発明の基本的なアイデアの概要を説明する。本発明のキーポイントは、プログラムの変数間の制約をあらわすＭ２Ｌ式を生成し、式中の変数が、プログラムの変数に対応する仕様(specification)をＭ２Ｌで記述することである。この技法によれば、ＭＯＮＡ(http://www.brics.dk/mona/)などの定理証明技法を用いて、変数が制約を満たすかどうかの解釈を自動的に見出すことができる。すなわち、文法ベースの文字列解析で行なわれているような、抽象的な文字列の値の変形を考慮する必要がない。
【００４０】
もしプログラムとその仕様から合成された式を満足する解釈を見出すことができるなら、そのプログラムは、潜在的に、その仕様を満たすことになる。こうして、その式が、どのような解釈の下でも成立するなら、そのプログラムは常に、その仕様をみたすことになる（順方向解析）。さもなければ、その仕様を満たさない反例が得られる。さらにまた、その仕様を満たすプログラム変数の文字列の値も得られる（後ろ向き解析）。
【００４１】
＜順方向解析＞
まず、次のようなJava(商標)のプログラムを考える。
String a = "a";
String b = "b";
String s;
if (flag) { s = a + b; }
else { s = b + a; }
System.out.println(s);
【００４２】
このプログラムから、次のような式Progを生成することができる。
Prog(Va,Vb,Vs) ≡
"a"(Va)∧"b"(Va)∧(concat(Vs,Va,Vb)∨concat(Vs,Vb,Va))
【００４３】
ここで、直感的に、Va,Vb,Vsの各々が変数をあらわすものとする。"c"(P)は、Pによってあらわされる文字列がcであるなら真となる述語である。
【００４４】
concat(R,P,Q)は、Rによってあらわされる文字列が、PとQによってあらわされる文字列の結合によって生成されるなら真となる述語である。
【００４５】
ここで、文字列"<"を、安全でない文字列と仮定すると、そのプログラムの安全仕様は、次のようになる。
Spec(Vs) ≡ ∀P⊆Vs.¬"<"(P)
【００４６】
すると、次の式をチェックすることによって、そのプログラムが、その仕様を満たすことを見出すことができる。
Prog(Va,Vb,Vs) ⇒ Spec(Vs)
ここで、Va,Vb,Vsは、自由変数である。
【００４７】
もし、プログラム変数bの値が、プログラムの外から来るなら、プログラム変数bの部分式を用いることなく、次のような制約が得られる。
Prog'(Va,Vb,Vs) ≡
"a"(Va)∧(concat(Vs,Va,Vb)∨concat(Vs,Vb,Va))
【００４８】
そうして、Prog'(Va,Vb,Vs) ⇒ Spec(Vs)をチェックすることによって、
"<"(Vb)のような反例を得ることができる。
【００４９】
＜後向き解析＞
文字列の値が未知のとき、仕様（制約）を満足させる変数bの値を見出すための式を生成することができる。
Prog'(Va,Vb,Vs) ∧ Spec(Vs)
【００５０】
＜Ｍ２Ｌにおける文字列と組込み関数のエンコーディング＞
Ｍ２Ｌにおいては、文字列の値の位置と、位置の部分集合はそれぞれ、１階変数と、２階変数によって直接記述することができる。本発明のエンコーディング技法においては、有限文字列をヒープと考える。これは、プログラムと仕様から生成されたＭ２Ｌ式を満たす。プログラム中で構築される文字列は、そのヒープの位置の集合によってあらわすことができる。例えば、"abcabc"というヒープ文字列があったとして、位置の集合{0,2}と{2,5}はそれぞれ、文字列"ac"と文字列"cc"をあらわす。ヒープ中の各キャラクタは、Ｍ２ＬにおけるM2L{Str}[5]をエンコーディングする方法の場合、ビット・ベクトルによってあらわすことができる。１バイト文字をあらわすために、８つの２階変数
B0,...,B7が必要である。ここで、Biは、i番目のビットが1である文字の位置を含む。
【００５１】
すると、文字"a"をあらわす述語"a"(P)は、８つの２階変数
B0,...,B7を用いて、次のようにあらわされる。
【数１】
2011013810.tif 000003
【００５２】
このエンコーディング方法により、文字列結合述語は、次のように定義することができる。
concat(R,P,Q) ≡ R = P∪Q
∧(∀p,q . p∈P∧q∈Q ⇒ p<q)
他の文字列演算もＭ２Ｌで同様に定義される。
【００５３】
ここで、図２を参照して、本発明のこの実施例に係る処理の機能ブロックについて説明する。まず、ソースコード２０２は、典型的にはＪａｖａのソースコードで、一般的には、テキストファイルの形式で、ハードディスク・ドライブ１０８に格納されている。
【００５４】
ＳＳＡコンバータ２０４は、この実施例では、ＪａｖａのソースコードをＳＳＡ形式のファイル２０６に変換する機能を有する。そのようなツールは、例えば、http://wala.sourceforge.net/から入手可能である。ＳＳＡとは、静的単一代入形式(Static Simple Assignment)のことであり、変数の定義が字面上唯一になるように添字をつけた中間表現形式であり、コンパイラにおけるデータフロー解析や最適化を見通しよく行うのに適している。
【００５５】
Ｊａｖａ以外に、Ｃ、Ｃ＋＋など様々なプログラミング言語のソースコードに対応してＳＳＡコンバータが存在しており、そのようなＳＳＡコンバータを導入することにより、この実施例では、Ｊａｖａ以外の言語のソースコードも取り扱うことができる。
【００５６】
このようにして変換されたＳＳＡプログラム２０６は、ハードディスク・ドライブ１０８に一旦保存してもよいし、主記憶１０８にロードしてもよい。
【００５７】
述語生成器２０８は、本発明の主要な特徴を具現化するプログラムであって、ＳＳＡプログラム２０６と、組込み関数の抽象集合を記述したファイル２１０を読み取って、Ｍ２Ｌソルバ２１４にかけるための述語宣言２１２を生成する機能をもつ。組込み関数の抽象集合を記述したファイル２１０は、予め用意される内容であって、好適にはハードディスク・ドライブ１０８に格納されている。
【００５８】
述語生成器２０８自体は、Ｃ、Ｃ＋＋、Ｃ＃、Ｊａｖａ（商標）、Ｐｅｒｌ、Ｒｕｂｙ、Ｐｙｔｈｏｎなどの任意のプログラミング言語で書くことができる。述語生成器２０８のプログラムは、ハードディスク・ドライブ１０８に格納され、キーボードの操作などに応答して、オペレーティング・システムの働きによって主記憶１０６にロードされ実行される。
【００５９】
このようにして変換された述語宣言２１２は、ハードディスク・ドライブ１０８に一旦保存してもよいし、主記憶１０８にロードしてもよい。
【００６０】
生成された述語宣言２１２は、予めユーザによってＭ２Ｌで書かれて好適にはハードディスク・ドライブ１０８に格納されている制約のファイル２１６とともに、Ｍ２Ｌソルバ２１４に読み込まれ、その処理結果は、ディスプレイ１１４の出力２１８の形式で表示される。
【００６１】
Ｍ２Ｌソルバ２１４は、これには限定されないが、好適には、MONAであり、http://www.brics.dk/mona/download.htmlから入手可能である。
【００６２】
＜本発明のアルゴリズムの概要＞
次に、図３及び図４のフローチャートを参照して、本発明のアルゴリズムの概要を説明する。上述のように、本発明のこの実施例では、検証入力は、ＳＳＡプログラム入力Progと、ターゲット変数xtと、仕様Specである。そのような仕様は、可能的には解析対象変数xtに割り当てられる文字列の性質をあらわす。
【００６３】
さて、図３において、最初のステップ３０２は、準備ステップであって、２つの文字列の結合は、２つの位置集合Ｓ1とＳ2の和集合によってあらわされるように、位置集合Rが、文字の順序を失うことなく文字列vをあらわすことを言明する述語"v"を定義することである。ここで、Ｓ1の全ての位置は、Ｓ2の全ての位置よりも下位にある。
【００６４】
次のステップ３０４も、準備ステップであって、||f||(R,"v1",...,"vn")が全ての入力文字列の値v1,...,vnと、戻り値f(v1,...,vn)をあらわす位置集合Rについて成立するように全ての組込み関数fについて、高階述語 ||f|| を定義することである。
【００６５】
次のステップ３０６も、準備ステップであって、文字列にのみ関連する命令を得ることである。もし他の種類の命令もあるなら、そのような命令ももとのプログラムから抽象することができる。
【００６６】
次のステップ３０８は、述語変換器２０８に関するものであり、図４のフローチャートにより詳細に示すように、プログラムProg中のすべての命令を、次のようにして述語宣言に変換することによって、Ｍ２Ｌ述語宣言の組を生成する。
【００６７】
すなわち、図４において、ステップ４０２では、述語変換器２０８は、まだ読み込む命令があると判断すると、ステップ４０４で、命令を読み取る。
【００６８】
ステップ４０６で、述語変換器２０８が、命令が文字列の代入x = vであると判断したなら、ステップ４０８で、それを、progx(R) ≡ "v"(R)に変換する。
【００６９】
ステップ４１０で、述語変換器２０８が、命令が未定義のプログラム変数xを導入すると判断したなら、ステップ４１２で、それを、宣言progx(R) ≡ R = Xxに変換する。ここで、Xxは、プログラム変数xに対応する自由変数である。
【００７０】
ステップ４１４で、述語変換器２０８が、命令が、組込み関数の呼び出しx =f(x1,...,xn)であると判断したなら、
ステップ４１６で、それを、宣言progx(R) ≡ ||f||(R,progx1,...,progxn)に変換する。
ここで、||f||(R,progx1,...,progxn)は、高階述語 ||f||を、変数Rと、述語progx1,...,progxnでインスタンス化することによって得られる。
【００７１】
ステップ４１８で、述語変換器２０８が、命令が、Φ命令x=Φ(x1,...,xn)であり、変数xの定義が循環的でないと判断したなら、ステップ４２０で、それを、
宣言progx(R) ≡ progx1(R)∨...∨progxn(R)に変換する。
【００７２】
ステップ４２２で、命令が、Φ命令x=Φ(x1,...,xn)であり、変数xの定義が循環的であるなら、述語変換器２０８は、次のようにする。
ステップ４２４で、もし定義が文字列の結合によってのみ影響されると判断したなら、ステップ４２６で、非循環変数を終端の変数と考え、非循環変数が対応するＭ２Ｌ述語に変換されるような正規文法をあらわすＭ２Ｌ述語宣言progxを構築することによって、その変数に関連する命令を正規文法（または、正規表現）に変換する。
そうでないなら、ステップ４２８で、循環的定義を固定回数だけアンロール(unroll)し、またはループ不変量を自動的に見出す技術を使用する。
【００７３】
こうして１つの命令の処理が終わるとステップ４０２に戻り、まだ命令があるなら、ステップ４０４で命令を読み取って、ステップ４０６以下を繰り返す。
【００７４】
そうでないなら、処理を終わって、図３のフローチャートの処理に戻る。
【００７５】
図３に戻って、ステップ３１０は、証明ソルバの記述であり、"v"の述語宣言と、Ｍ２Ｌ述語Predの集合と、Ｍ２Ｌ式∀S . progxt(S) ⇒ Spec(S)をＭ２Ｌソルバに入力する。そして、Ｍ２Ｌソルバから結果を受け取る。
【００７６】
次に、本発明の背景の理論的な詳細を説明する。
＜プログラム＞
プログラムは、ＳＳＡの形式で表現される。ＳＳＡについては、下記の文献を参照されたい。
B. K. Rosen, M. N. Wegman, F. K. Zadeck, Global value numbers and redundant
computations, 
Proceedings of the 15th ACM SIGPLAN-SIGACT symposium on Principles of 
programming, San Diego, California, United States 
Pages: 12 - 27, 1988 
Ron Cytron, Jeanne Ferrante, Barry K. Rosen, Mark N. Wegman, 
F. Kenneth Zadeck, 
Efficiently computing static single assignment form and the control
dependence graph 
Source  ACM Transactions on Programming Languages and Systems (TOPLAS)
archive, Volume 13 ,  Issue 4  (October 1991) 
【００７７】
ＳＳＡの抽象的なシンタックスは、以下のとおりである。
x ∈ Ｘ
n ∈ Ｎ
v ∈ Ｖ
x' ::= x|¬x|⊥
s ::= x = v   ステートメント
| x = undefined
| x = f(x1,...,xn)
| x = Φ(x1,...,xn)
b ::= (n,{s})  基本ブロック
Ｎ ::= {b}     基本ブロックの集合
Ｅ ::= {(b,b,x')}  エッジの集合
Ｇ ::= (N,E') プログラム（制御フロー・グラフ）
【００７８】
x ∈ Ｘとv ∈ Ｖはそれぞれ、変数と値をあらわす。n ∈ Ｎは基本ブロックの識別子である。(n,{s})は基本ブロック識別子nと、命令の集合{s}とからなる基本ブロックである。
【００７９】
Ｅは、２つの基本ブロックbと、条件x'によってあらわされるエッジの集合であり、ここで、条件は、変数、変数の否定、または特殊な値botによってあらわされる。ＳＳＡ命令は、定数値の代入(x = v)、関数呼出し(x = f(x1,...,n))、またはΦ関数(x = Φ(x1,...,xn))である。基本ブロックbは、分岐もループもないステートメントの列である。分岐やループなどの制御フローは、制御フロー・グラフgのエッジとしてあらわされる。
【００８０】
＜単項２階論理＞
この発明では、変数の間の制約をあらわす文字列上で、単項２階論理が使用される。Ｍ２Ｌ(str)の抽象的なシンタックスは、次のとおりである。
【数２】
2011013810.tif 000004
【００８１】
なお、この実施例を通して、次の述語を使用する。ここで、"a"(P)は、Pによってあらわされる文字列がaであることを示す。
【数３】
2011013810.tif 000005
【００８２】
次に、アルゴリズムのコアの部分について説明する。
＜組込み関数の抽象＞
組込み関数の抽象は、Ｍ２Ｌ述語によって予め定義されている。すなわち、組込み関数fの抽象は、記号||f||であらわされる。組込み関数のパラメータは、黙示的には高階変数であらわされ、それは、述語で置き換えることができる。各高階変数は、述語によってインスタンス化されると想定され、その述語は、命令の抽象化の時点で、組込み関数のパラメータに割り当てられた文字列の値の特性をあらわす。
【００８３】
ここで、sで指定された文字列から、xで指定された文字列のすべての出現を除去する、remove(s,x)関数を考えてみる。この文字列の場合、||remove||は、次のように定義される。ここで、Ps, Pxは高階変数であり、R, S, Xは２階変数である。
【数４】
2011013810.tif 000006
【００８４】
文字列連結に関しては、次のような抽象化を使用する。
【数５】
2011013810.tif 000007
【００８５】
文字列xにおけるyの出現をzで置換する置換関数replace(s,x,y)は、次のような抽象化が使用される。
【数６】
2011013810.tif 000008
【００８６】
解析を健全にするために、関数fの抽象化は、次の性質を満たさなくてはならない。
【数７】
2011013810.tif 000009
ここで、ww'は、有限文字列wとw'の連結をあらわし、下記の式は、式Ψが、有限の文字列wと、代入Iについて成立することを示す。
Lw,I(Ψ)は、Ψによってあらわされる文字列の集合であり、下記のとおり定義される。
【数８】
2011013810.tif 000010
【００８７】
＜変数と命令の抽象化＞
命令を抽象化したものが、Ｍ２Ｌ述語の宣言である。もし変数の循環的な定義がないなら、変数と命令の抽象化は、下記のとおりとなる。
【数９】
2011013810.tif 000011
【００８８】
もし、各命令sの抽象が、下記に示すように、述語の宣言なく再帰的に定義される。ここで、def(x)は、変数xを定義する命令を返す。
【数１０】
2011013810.tif 000012
【００８９】
もし、Φ命令の左側の変数が、それ自身によって定義されるなら、その変数は、循環(cyclic)変数と呼ばれる。そのような循環変数は、ループまたは再帰をもつプログラムを解析するときのみあらわれる。
【００９０】
もし循環変数の値が、文字列の結合によってのみ影響を受けるなら、非特許文献２にあるように、循環変数について文脈自由文法を先ず構成し、それを正規言語で近似する。次に正規文法がエンコードされ、それは、Ｍ２Ｌで、その循環変数がとりえる可能的な文字列の値をあらわす。正規言語のエンコーディングは、基本的には、
http://www.brics.dk/mona/publications.htmlの６．６章の記載内容と同様であるが、異なるのは、この発明の方法では、終端記号として考えることができる、非循環変数のプログラム変数に対応する述語が使用できる、ということである。
【００９１】
下記は、そのエンコーディングの定義であり、ここで、Tは文字をあらわす終端記号であり、Txは、プログラム変数xに対応する終端記号をあらわし、変数N, N1, N2は、非終端記号をあらわす。
【数１１】
2011013810.tif 000013
【００９２】
そうでないなら、そのようなプログラムは、固定回数アンロール(unroll)されることによって、ループのないプログラムに変更され、あるいは後述の技法をもちいて、循環変数に対してループ不変量が見出される。
【００９３】
＜基本ブロックと制御フローの抽象化＞
この解析は、フローや条件を考慮したものではないので、基本ブロックと制御フローの抽象化は、下記のように、直接的なものとなる。
【数１２】
2011013810.tif 000014
【００９４】
次に、拡張と変形について述べる。
＜手続間解析＞
今まで、手続内解析だけを述べてきたが、これは、容易に手続間解析に拡張することができる。そのアルゴリズムを説明するためにまず、コールグラフのシンタックスを次のように定義する。
m ∈ Ｍ
Ｎ' ::= {(m,g)}
Ｅ' ::= {((m,g),(m,g))}
Ｄ  ::= {((x,m),{(x,m)})}
cg  ::= {(Ｎ',Ｅ',Ｄ)}
【００９５】
Ｍはコールグラフのノードであり、cgはコールグラフであり、Ｎ'はノード名と制御フローグラフの対からなるコールグラフ・ノードの集合であり、Ｅ'はコールグラフのエッジの集合であり、Ｄは、関数呼び出しによって引き起こされるパラメータと戻り値の直接データ依存性の集合である。
【００９６】
((x,m),{(x1,m1),...,(xn,mn)}) ∈ Ｄは、対応するコールグラフ・ノードm1,...,mn中の変数x1,...,xnの値が、コールグラフ・ノードmの値xに流れることをあらわす。
【００９７】
ここで、もし再帰的呼び出しがないなら、コールグラフの抽象は、次のように定義される。
【数１３】
2011013810.tif 000015
【００９８】
ノード名は、コールグラフ・ノードから生成される述語をアノテート(annotate)するために、命令の抽象に伝播する。
【００９９】
＜ラベル付けされたストリングの解析＞
ラベル付けされたストリングの解析は、ストリングの解析の変形であって、各文字が、汚染(taintedness)などの追加の情報をもっている。そのようなラベルは、追加のビットを使用することにより、あらわすことができる。例えば、汚染文字と非汚染文字をあらわしたいなら、１バイト文字を9ビットであらわす。
【０１００】
＜条件を考慮した文字列解析＞
条件を考慮した解析の場合、下記に示す抽象化を行う。
【数１４】
2011013810.tif 000016
ここでπは、変数と基本ブロックの対から制約へのマッピングである。その制約は、指定された基本ブロックで使用されている指定された変数をアサートし、それはＭ２Ｌ式であらわされると想定される。そのようなπは、本出願人に係る、米国特許第７５３０１０７号に記載されているのと同一の方法で、計算することができる。
【０１０１】
＜ループ不変量の発見＞
もし循環変数xについてループ不変量invxがあるなら、関数呼び出しの抽象化に、progxの代わりにこの述語を使用することができる。そのようなループ不変量を見出すために割り当てられる文字列の値からなる全ての文字を含む文字集合をあらわすために、自由（位置集合）変数CSxを導入する。
【０１０２】
こうして、ループ不変量invxは、次のように定義される。
invx ≡ construct(R,CSx)
ここで、construct(R,S) ≡ R ⊆ S
【０１０３】
述語construct(R,S)は、位置集合Rによってあらわされる文字列の値が、位置集合の文字列からなることを言い述べる。すると、invxはループ不変量なので、CSxを制約するために、次のような仮定が必要である。
∀R . progx(R) ⇒ invx(R)
【０１０４】
こうして、仕様Specyをもつプログラム変数yの検証は、次の式で行われる。
(∀R . progx(R) ⇒ invx(R))
⇒ (∀R . progy(R) ⇒ Specy(R))
【０１０５】
上記式の一般化は、次のとおりである。ここでXは、循環プログラム変数の集合である。
(∨x∈X ∀R . progx(R) ⇒ invx(R))
⇒ (∀R . progy(R) ⇒ Specy(R))
【０１０６】
＜正規表現の演算＞
http://www.brics.dk/mona/publications.htmlにあるようなＭ２Ｌの典型的な正規表現のエンコーディング方法と同様に、この発明の実施例でも、正規表現のパターンマッチングを使用して、それを正規表現の演算に使用することができる。エンコーディング方法は、数１１にあるのと同様である。例えば、正規表現(ab)*は、次のようにあらわすことができる。
is_ab_star(V) ≡
∃R . min(V) ∈ R ∧ max(V) + 1 ∈ R  ∧
∀r,r',S . consecutive(r,r',R) ∧ strr(S,V,r,r')
⇒ "ab"(S)
【０１０７】
＜文字列インデックスの取り扱い＞
インデックスは、位置と、位置の集合の対でエンコードすることができる。例えば、プログラム定文字列"ace"が、Ｍ２Ｌで位置集合{0,2,4}でエンコードされるなら、文字列"ace"のインデックスは、対(2,{0,2,4})によってエンコードされる。
【０１０８】
そこで、上述のエンコーディングに基づき、Ｍ２Ｌ中の文字列をあらわすために、述語pos0, ..., posnを導入する。ここで、posn(p,S)は、位置集合S中の位置pが、位置集合Sに対応する文字列のインデックスnをあらわすことを言い述べる。
【数１５】
2011013810.tif 000017
【０１０９】
JavaのIndexOfメソッドは、次のように抽象化される。
【数１６】
2011013810.tif 000018
ここで、||indexOf||の第１のパラメータは位置であり、第２のパラメータは、その位置を含む文字列をあらわす。このように、文字列インデックスを扱う関数の呼び出しについては、僅かに異なる抽象化が使用される。
【０１１０】
さらに、文字列sのインデックスnとインデックスmの間の部分文字列を抽出する別の文字列演算substring(s,n,m)を考えてみる。すると、文字列演算は、次のように抽象化される。
【数１７】
2011013810.tif 000019
【０１１１】
上述の例を考慮すると、インデックスの置換と、関数呼び出しの命令は、次のように抽象化される。
【数１８】
2011013810.tif 000020
【０１１２】
以下では、理解を助けるために、いくつかの例を示す。
先ず下記は、文字列の値を出力するJava(商標)のプログラムである。
static public void main(String args[]){
String uname = args[0];
String group = args[1];
if (group.equals("IBM")) {
System.out.println(uname + "(IBM)");
} else {
uname = uname.replace("<","&lt;");
System.out.println(uname);
}
}
【０１１３】
次に示すのは、上記Java(商標)のプログラムのＳＳＡ形式である。
G  =  (N, E) 
N  =  {b1, b2, b3, b4} 
E  =  {(b1,b2,v2), (b1,b3,¬ v2), (b2, b4), (b3, b4) } 
b1  =  (1, BB1) 
b2  =  (2, BB2) 
b3  =  (3, BB3) 
b4  =  (4, BB4) 
BB1  = 
uname = undefined; 
group = undefined; 
v1 = "(IBM)"; 
v2 = equals(group,v1) 
BB2  = 
v3 = uname + v1; 
System.out.println(v3) 
BB3  = 
v4 = "<"; 
v5 = "lt;"; 
v6 = replace(uname,v4,v5); 
System.out.println(v6) 
BB4  =  φ
【０１１４】
本発明によれば、上記ＳＳＡ形式に対応するＭＯＮＡの述語が下記のように得られる。
pred prog_v1(var2 R) =
ex2 c1,c2,c3,c4,c5 where is_lparen(c1) & is_I(c2) & is_B(c3) & is_M(c4) & is_rparen(c5):
ex2 S1,S2,S3,S4,S5:
S1 = empty & concat(S2,c1,S1) & concat(S3,c2,S2) &
concat(S4,c3,S3) & concat(S5,c4,S4) & concat(R,c5,S5);
pred prog_v2(var2 R) =
ex2 P: prog_v1(P) & (R = P);
var2 uname;
var2 group;
pred prog_uname(var2 P) = P = uname;
pred prog_group(var2 P) = P = group;
pred prog_v3(var2 R) =
ex2 P,Q: prog_uname(P) & prog_v1(Q) & concat(R, P, Q);
pred prog_v4(var2 R) =
is_lt(R);
pred prog_v5(var2 R) =
ex2 c1,c2,c3,c4 where is_amp(c1) & is_l(c2) & is_t(c3) & is_semicolon(c4):
ex2 S1,S2,S3,S4:
concat(S2,c1,c2) & concat(S3,c2,S2) &
concat(S4,c3,S3) & concat(R,c4,S4);
pred prog_v6(var2 R) =
ex2 S,X',Y':
prog_uname(S) &
(all1 x : (x in X' <=> ex2 X : x in X  substr(X, S) & prog_v4(X))) &
(all1 y : (y in Y' <=> ex2 Y : y in Y  substr(Y, R) & prog_v5(Y))) &
R ／ Y' = S ／ X';
pred Spec(var2 P) =
all1 p where p in P: ~is_lt({p});
var2 S;
prog_v6(S) => Spec(S);
【０１１５】
上記で、prog_ｘは、progxに対応し、is_a(c)は、式 "a"(c)に対応する。さらに、ex1, all1, ex2, all2はそれぞれ、１階変数と、２階変数の修飾子である。
【０１１６】
下記は、正規表現の演算によって更新される文字列の値を出力するJava(商標)プログラムである。
static public void main(String args[]){
String s = args[0];
s = s.replaceAll("(ab)+", "z")
System.out.println(s);
}
【０１１７】
それの対応するＳＳＡ形式は、下記のとおりである。
G  =  (N, E) 
N  =  {b1,b2} 
E  =  {(b1, b2)} 
b1  =  (1, BB1) 
b2  =  (2, BB2) 
BB1  = 
s  = undefined; 
v1 = "(ab)*"; 
v2 = "z"; 
v3 = replaceAll(s,v1,v2); 
System.out.println(v3) 
BB2  =  φ
【０１１８】
本発明によれば、上記ＳＳＡ形式に対応するＭＯＮＡの述語が下記のように得られる。
include "sa.mona";
pred prog_v1(var2 R) =
ex2 P: min(R) in P &  max(R)+1 in P &
all1 r,r': all2 S: consecutive(r,r',P) & strr(S,R,r,r') => is_ab(S);
pred prog_v2(var2 R) = is_z(R);
var2 Xs;
pred prog_s(var2 R) = R = Xs;
pred prog_v3(var2 R) =
ex2 S,X',Y':
prog_args0(S) &
(all1 x : (x in X' <=> ex2 X : x in X & substr(X, S) & prog_v1(X))) &
(all1 y : (y in Y' <=> ex2 Y : y in Y & substr(Y, R) & prog_v2(Y))) &
R \ Y' = S \ X';
pred Spec(var2 P) =
~(ex2 S: substr(S,P) & is_ab(S));
var2 V3;
prog_v3(V3) => Spec(V3);
ここで、prog_v1が、正規表現"(ab)*"をあらわす述語である。
【０１１９】
次のＳＳＡ形式は、循環変数v2をもつ。なお、ここでは便宜上、制御フローグラフは省略した。
v0 = "ab"
v1 = "ab"
v2 = phi(v0,v3)
v3 = v2 + v1
【０１２０】
v2がとりえる文字列の値は、次の文脈自由文法によってあらわすことができる。
v2 → v0|v2
v3 → v2 v1
【０１２１】
文脈自由文法は、正規表現v0 v1*で近似できるので、次のようなＭＯＮＡプログラムが得られる。
pred prog_v0(var2 R) = is_ab(R);
pred prog_v1(var2 R) = is_ab(R);
pred prog_v2(var2 R) =
ex2 V0,V1Star:
prog_v1(V0) &
(ex2 P: min(V1Star) in P & max(V1Star)+1 in P &
all1 r,r': all2 S: consecutive(r,r',P) &
strr(S,V1Star,r,r') => prog_v1(S)) &
concat(R, V0, V1Star);
pred prog_v3(var2 R) =
ex2 V1,V2:
prog_v2(V2) & prog_v1(V1) & concat(R, V2, V1);
【０１２２】
次のＳＳＡプログラムは、indexOfの呼び出しをもつ。なお、ここでも制御フローは省略した。
v0 = 0;
v1 = "ab";
v2 = "b";
v3 = indexOf(v1,v2);
v4 = substring(v1,v0,v3);
【０１２３】
これは、次のようなＭＯＮＡプログラムに変換される。
include "sa.mona";
pred prog_v0(var1 n, var2 S) = pos0(n,S);
pred prog_v1(var2 R) = is_ab(R);
pred prog_v2(var2 R) = is_b(R);
pred prog_v3(var1 n0, var2 S0) =
(ex2 S1: prog_v2(S1) & indexOf(n0, S0, S1)) &
(all2 S1: all1 m:
prog_v2(S1) & indexOf(m,S0,S1) => n0 <= m);
pred prog_v4(var2 R) =
ex2 V1: ex1 v0,v3:
prog_v0(v0,V1) & prog_v1(V1) & prog_v3(v3,V1) &
substrr(R, V1, v0, v3);
pred Spec(var2 R) =
all2 R': R' sub R => ~is_b(R');
var2 R;
prog_v4(R) => Spec(R);
【０１２４】
次のＳＳＡプログラムは、ループをもつ。なお、ここでも制御フローは省略した。
v1 = ...
v2 = "a"
v3 = "b"
v4 = replace(v5,v2,v3)
v5 = phi(v1,v4)
【０１２５】
これは、次のようなＭＯＮＡプログラムに変換される。
include "sa.mona";
# R is a string constructed from a character
# set S by selecting positions.
# Ex.: Suppose w = "abc", S = {0,1,2}, then
#      R = {0}|{1}|{2}|{0,1}|{0,2}|{1,2}|{0,1,2}
pred construct(var2 R, S) = R sub S | R = S;
var2 CSv5;
var2 args0;
pred inv_v5(var2 R) = construct(R, CSv5);
pred prog_v1(var2 R) = is_b(R);
pred prog_v2(var2 R) = is_a(R);
pred prog_v3(var2 R) = is_b(R);
pred prog_v4(var2 R) =
ex2 S,X',Y':
inv_v5(S) &
(all1 x :
(x in X' <=> ex2 X : x in X &
substr(X, S) & prog_v2(X))) &
(all1 y :
(y in Y' <=> ex2 Y : y in Y &
substr(Y, R) & prog_v3(Y))) &
(R \ Y' sub S \ X');
pred prog_v5(var2 R) =
prog_v1(R) | prog_v4(R);
pred SpecA(var2 P) =
all1 p where p in P: ~is_a({p});
(all2 R: prog_v5(R) => inv_v5(R))
=> all2 S: prog_v5(S) => SpecA(S);
【０１２６】
以上、本発明を実施の形態を用いて説明したが、上記実施の形態に、多様な変更または改良を加えることが可能であり、その様な変更または改良を加えた形態も本発明の技術的範囲に含まれ得ることが、この分野の当業者に明らかであろう。例えば、本発明は、特定のコンピュータのアーテテクチャやＯＳなどのプラットフォームに依存しない。
【０１２７】
また、Ｊａｖａ（商標）に限らず、文字列を扱う任意のコンピュータ言語のソースコードに適用可能である。その際、好適には一旦ＳＳＡ形式に変換するのが望ましいが、コンピュータ言語のソースコードから直接Ｍ２Ｌ形式に変換するようにしてもよい。
【０１２８】
さらに、Ｍ２Ｌソルバとして、この実施例ではＭＯＮＡを使用したが、これには限定されず、プラットフォームで使用可能な任意のＭ２Ｌソルバを使用することができる。
【符号の説明】
【０１２９】
２０２・・・ソースコード
２０４・・・ＳＳＡコンバータ
２０８・・・述語生成器
２１０・・・組込み関数の抽象集合
２１４・・・Ｍ２Ｌソルバ
２１６・・・Ｍ２Ｌで書かれた仕様
【図１】
2011013810.tif 000021
【図２】
2011013810.tif 000022
【図３】
2011013810.tif 000023
【図４】
2011013810.tif 000024