(57)【要約】【課題】静的解析ツールを利用することなく品質の高いソフトウェアを製造することができる。【解決手段】ユーザ端末２と、ユーザ端末２からソースコードを受信してプリプロセッシングを実施するビルドサーバ４とを備えたオンラインビルドシステム１であって、ビルドサーバ４は、所定のコードのパターンと、前記ソースコード内のバグの可能性を発見する契機となる又はバグに対処するコード記述とが対応づけられた作り込み抑制情報が格納された記憶部と、前記作り込み抑制情報を参照して前記ソースコードを検索し、前記パターンを発見した場合に、前記コード記述を当該ソースコードに追加するプリプロセッシングを実行するプリプロセッシング実行部と、を備えることを特徴とする。【選択図】図１
2015197902.tif 000002
【特許請求の範囲】
【請求項１】
ユーザ端末と、前記ユーザ端末からソースコードを受信してプリプロセッシングを実施するビルドサーバとを備えたオンラインビルドシステムであって、
前記ビルドサーバは、
所定のコードのパターンと、前記ソースコード内のバグの可能性を発見する契機となる又はバグに対処するコード記述とが対応づけられた作り込み抑制情報が格納された記憶部と、
前記作り込み抑制情報を参照して前記ソースコードを検索し、前記パターンを発見した場合に、前記コード記述を当該ソースコードに追加するプリプロセッシングを実行するプリプロセッシング実行部と、を備える、
ことを特徴とするオンラインビルドシステム。
【請求項２】
前記ビルドサーバは、
前記プリプロセッシング後のソースコードのコンパイルを実行するコンパイル実行部をさらに備える、
ことを特徴とする請求項１に記載のオンライビルドシステム。
【請求項３】
ユーザ端末と、前記ユーザ端末からソースコードを受信してプリプロセッシングを実施するビルドサーバとを備えたオンラインビルドシステムのオンライビルド方法であって、
前記ビルドサーバは、
所定のコードのパターンと、前記ソースコード内のバグの可能性を発見する契機となる又はバグに対処するコード記述とが対応づけられた作り込み抑制情報が格納された記憶部を有し、
前記作り込み抑制情報を参照して前記ソースコードを検索する検索ステップと、
前記パターンを発見した場合に、前記コード記述を当該ソースコードに追加するコード追加ステップとを実行する、
ことを特徴とするオンラインビルド方法。
【請求項４】
請求項３に記載のオンラインビルド方法をオンラインビルドシステムとしてコンピュータに実行させるためのオンラインビルドプログラム。
【発明の詳細な説明】
【技術分野】
【０００１】
本発明は、ソフトウェアの品質向上を実現するオンラインビルドシステム、オンラインビルド方法およびオンラインビルドプログラムに関する。
【背景技術】
【０００２】
従来、実行環境上のプログラム記述言語仕様に基づいて開発されたプログラムを、開発環境上のコンパイラ仕様に整合させる技術が提案されている（特許文献１参照）。プログラムの開発者は、特許文献１に記載された技術を用いて単体試験工程（以下、ＵＴ）を行うことで、的確かつ効率的にバグの発見・修正を行うことができる。
【先行技術文献】
【特許文献】
【０００３】
【特許文献１】特開平５−１９７５３９号公報
【発明の概要】
【発明が解決しようとする課題】
【０００４】
一方、バグの中にはＵＴで発見が困難なものも存在する。セキュリティに脆弱なコード、性能懸念のあるコード等をソースコードに用いている場合である。これらは、ソフトウェア開発（コーディング）が手作業で行われている限り、どのような熟練者が開発してもなくすことが難しい「バグ」である。
【０００５】
これらのバグを取り除く方法として、静的解析ツール（coverity（登録商標）等）を用いて静的リファクタリングを実施することが知られている。しかしながら、静的解析ツールの利用には、以下に示す問題があった。
【０００６】
第１に、静的解析ツールのインストールの問題があった。すなわち、静的解析ツールを利用するためには、特殊なツールを開発端末へ個別にインストールしなければならなかった。この問題は、開発環境が大きく、開発端末の数が多い場合に特に問題となる。
【０００７】
第２に、解決策が不明瞭であるという問題がった。すなわち、静的リファクタリングを実施した結果、問題点が明らかになるものの、どのようなコーディングを行えばこの問題点が解決されるか（ソフトウェア品質が高まるか）が不明確である。この問題は、コーディング初心者が開発を行う場合に特に問題となる。
【０００８】
本発明は、前記問題に鑑みてなされたものであり、静的解析ツールを利用することなく品質の高いソフトウェアを製造することができる、オンラインビルドシステム、オンラインビルド方法およびオンラインビルドプログラムを提供することを課題とする。
【課題を解決するための手段】
【０００９】
前記課題を解決するため、本発明に係るオンラインビルドシステムは、ユーザ端末と、前記ユーザ端末からソースコードを受信してプリプロセッシングを実施するビルドサーバとを備えたオンラインビルドシステムであって、前記ビルドサーバが、所定のコードのパターンと、前記ソースコード内のバグの可能性を発見する契機となる又はバグに対処するコード記述とが対応づけられた作り込み抑制情報が格納された記憶部と、前記作り込み抑制情報を参照して前記ソースコードを検索し、前記パターンを発見した場合に、前記コード記述を当該ソースコードに追加するプリプロセッシングを実行するプリプロセッシング実行部と、を備えることを特徴とする。
【００１０】
また、本発明に係るオンラインビルド方法は、ユーザ端末と、前記ユーザ端末からソースコードを受信してプリプロセッシングを実施するビルドサーバとを備えたオンラインビルドシステムのオンライビルド方法であって、前記ビルドサーバが、所定のコードのパターンと、前記ソースコード内のバグの可能性を発見する契機となる又はバグに対処するコード記述とが対応づけられた作り込み抑制情報が格納された記憶部を有し、前記作り込み抑制情報を参照して前記ソースコードを検索する検索ステップと、前記パターンを発見した場合に、前記コード記述を当該ソースコードに追加するコード追加ステップとを実行する、ことを特徴とする。
【００１１】
また、本発明に係るオンラインビルドプログラムは、前記オンラインビルド方法をオンラインビルドシステムとしてコンピュータに実行させることを特徴とする。
【００１２】
このようにすることで、本発明に係るオンラインビルドシステムは、ソースコード上の脆弱性（バグ）の発見を手助けする又はバグに対処するコードを自動的に埋め込むことができる。その為、本発明に係るオンラインビルドシステムは、静的解析ツールを用いて静的リファクタリングを実施することなく、従来、単体試験工程（ＵＴ）で発見が困難とされていたバグをＵＴで発見することができる。オンラインビルド方法およびオンラインビルドプログラムについても、オンラインビルドシステムと同様である。
【００１３】
また、本発明に係るオンラインビルドシステムは、前記ビルドサーバが、前記プリプロセッシング後のソースコードのコンパイルを実行するコンパイル実行部をさらに備えることを特徴とする。
【００１４】
このようにすることで、本発明に係るオンラインビルドシステムは、プリプロセッシングされたコード以外にも、オブジェクトファイルや実行可能形式ファイルを生成することができる。また、コンパイラのバージョンや仕様に適合したプリプロセスが可能になる。その為、本発明に係るオンラインビルドシステムは、ユーザの求めに応じて種々の生成物を提供することが可能である。
【発明の効果】
【００１５】
本発明に係るオンラインビルドシステム、オンラインビルド方法およびオンラインビルドプログラムによれば、静的解析ツールを利用することなく品質の高いソフトウェアを製造することができる。
【図面の簡単な説明】
【００１６】
【図１】本発明に係るオンラインビルドシステムの概要を説明するための図である。
【図２】本実施形態に係るユーザ端末の機能構成図である。
【図３】本実施形態に係るアカウント管理サーバの機能構成図である。
【図４】本実施形態に係るアカウント情報ＤＢのデータ構成図である。
【図５】本実施形態に係るビルドサーバの機能構成図である。
【図６】本実施形態に係る作り込み抑制情報ＤＢのデータ構成図である。
【図７】本実施形態に係るオンラインビルドシステムのアカウント登録処理を示すシーケンス図である。
【図８】本実施形態に係るオンラインビルドシステムのビルド処理を示すシーケンス図である。
【図９】本実施形態に係るオンラインビルドシステムのプリプロセッシングの処理を示すフローチャートである。
【図１０】実施例１に係るプリプロセッシング処理を説明するための図であり、（ａ）はバグ有りのサンプルコードを示し、（ｂ）はバグ無しのサンプルコードを示し、（ｃ）はプリプロセッシング後のコード記述を示している。
【図１１】実施例２に係るプリプロセッシング処理を説明するための図であり、（ａ）はバグ有りのサンプルコードを示し、（ｂ），（ｃ）はバグ無しのサンプルコードを示している。
【図１２】実施例２に係るプリプロセッシング処理を説明するための図であり、（ｄ）はプリプロセッシング後のコード記述を示している。
【図１３】実施例３に係るプリプロセッシング処理を説明するための図であり、（ａ）はバグ有りのサンプルコードを示し、（ｂ），（ｃ）はバグ無しのサンプルコードを示している。
【図１４】実施例３に係るプリプロセッシング処理を説明するための図であり、（ｄ）はバグ無しのサンプルコードを示し、（ｅ）はプリプロセッシング後のコード記述を示している。
【図１５】実施例４に係るプリプロセッシング処理を説明するための図であり、（ａ）はバグ有りのサンプルコードを示し、（ｂ）はバグ無しのサンプルコードを示し、（ｃ）はプリプロセッシング後のコード記述を示している。
【図１６】実施例５に係るプリプロセッシング処理を説明するための図であり、（ａ）はバグ有りのサンプルコードを示し、（ｂ）はバグ無しのサンプルコードを示している。
【図１７】実施例５に係るプリプロセッシング処理を説明するための図であり、（ｃ）はプリプロセッシング後のコード記述を示している。
【図１８】実施例６に係るプリプロセッシング処理を説明するための図であり、（ａ）はバグ有りのサンプルコードを示し、（ｂ），（ｃ）はバグ無しのサンプルコードを示している。
【図１９】実施例６に係るプリプロセッシング処理を説明するための図であり、（ｄ）はプリプロセッシング後のコード記述を示している。
【図２０】実施例７に係るプリプロセッシング処理を説明するための図であり、（ａ）はバグ有りのサンプルコードを示し、（ｂ）はバグ無しのサンプルコードを示し、（ｃ）はプリプロセッシング後のコード記述を示している。
【図２１】実施例８に係るプリプロセッシング処理を説明するための図であり、（ａ）はバグ有りのサンプルコードを示し、（ｂ）はバグ無しのサンプルコードを示している。
【図２２】実施例８に係るプリプロセッシング処理を説明するための図であり、（ｃ）はプリプロセッシング後のコード記述を示している。
【図２３】実施例９に係るプリプロセッシング処理を説明するための図であり、（ａ）はバグ有りのサンプルコードを示し、（ｂ）はバグ無しのサンプルコードを示している。
【図２４】実施例９に係るプリプロセッシング処理を説明するための図であり、（ｃ）はプリプロセッシング後のコード記述を示している。
【発明を実施するための形態】
【００１７】
以下、本発明の実施するための形態を、適宜図面を参照しながら詳細に説明する。
各図は、本発明を十分に理解できる程度に、概略的に示してあるに過ぎない。よって、本発明は、図示例のみに限定されるものではない。なお、各図において、共通する構成要素や同様な構成要素については、同一の符号を付し、それらの重複する説明を省略する。
【００１８】
≪実施形態に係るオンラインビルドシステムの構成≫
図１に示す、オンラインビルドシステム１は、システムを利用する権利（アカウント）を特定の者に付与し、アカウントを有する者が所有するソースコード（拡張子：「.cpp」等）のビルドをオンラインで行うシステムである。
【００１９】
オンラインビルドシステム１は、ユーザ端末２，・・・，２と、アカウント管理サーバ３と、ビルドサーバ４とが通信回線（有線、無線を含む）を介して接続されている。以下では、各装置について説明する。
【００２０】
＜ユーザ端末＞
図２を参照して、ユーザ端末２の機能構成について説明する。ユーザ端末２は、オンラインビルドシステム１のユーザ（以下、単に「ユーザ」）が操作する装置である。ユーザ端末２では、ユーザによってソフトウェア開発が行われる。ユーザ端末２は、例えば、ＰＣ(Personal Computer)である。
【００２１】
ユーザ端末２を使用して行われるソフトウェア開発は、特定の言語、開発モデル、開発規模、タイミング等に限定されない。例えば、ソフトウェア開発は、Ｃ＋＋、ＦＯＲＴＲＡＮ、ＣＯＢＯＬ等のプリプロセッサを用いるコンピュータ言語であればいずれでもあってよい。ソフトウェア開発は、ウォーターフォールモデル、反復型開発、アジャイル開発等の一工程であってよい。また、ソフトウェア開発は、大規模、小規模を問わない。また、ソフトウェア開発は、新規プログラムの開発、既存プログラムの修正のどちらであってもよい。
【００２２】
ユーザ端末２は、記憶部１０と、制御部２０とを備えて構成される。記憶部１０は、ＲＡＭ（Random Access Memory）、ＲＯＭ（Read Only Memory）、ＨＤＤ（Hard Disk Drive）、フラッシュメモリ等の記憶媒体から構成される。制御部２０は、ユーザ端末２が備えるＣＰＵ（Central Processing Unit）によるプログラム実行処理や、専用回路等により実現される。制御部２０がプログラム実行処理により実現する場合、記憶部１０には、制御部２０の機能を実現するためのプログラムが格納される。
【００２３】
記憶部１０には、ユーザによって開発されたソースコード（拡張子：「.cpp」等）１１が格納されている。また、制御部２０には、アカウント登録要求部２１と、アカウント認証要求部２２と、ビルド要求部２３とが備えられている。ここでは、各機能の概要のみを説明し、詳細は「オンラインビルドシステムの動作」で後記する。
【００２４】
アカウント登録要求部２１は、ユーザからの指示によってアカウント登録要求を送信し、アカウント登録結果を受信する。ここで、アカウント登録要求の送信は、ビルドサーバ４を介してアカウント管理サーバ３に行われてもよいし、ユーザ端末２から直接行われてもよい。
【００２５】
アカウント認証要求部２２は、ユーザからの指示によってアカウント認証要求を送信し、アカウント認証結果を受信する。ここで、アカウント認証要求の送信は、ビルドサーバ４を介してアカウント管理サーバ３に行われてもよいし、ユーザ端末２から直接行われてもよい。アカウントの認証は、例えば、ユーザ端末２からビルドサーバ４に対してソースコードのビルドの依頼がなされた場合に行う。
【００２６】
ビルド要求部２３は、ユーザからの指示によってビルドサーバ４に対してソースコードを送信し、ソースコードから生成した生成物を受信する。ソースコードからの生成物は、ソースコードをビルドすることで生成されるものであり、例えば、（１）プリプロセッシングされたソースコード（拡張子：「.cpp」等）、（２）オブジェクトファイル（拡張子：「.o」等）、（３）実行可能形式ファイル（拡張子：「.exe」等）のことである。
【００２７】
＜アカウント管理サーバ＞
図３を参照して、アカウント管理サーバ３の機能構成について説明する。アカウント管理サーバ３は、ユーザのアカウントの管理を行う装置である。
【００２８】
アカウント管理サーバ３は、記憶部３０と、制御部４０とを備えて構成される。記憶部３０は、ＲＡＭ（Random Access Memory）、ＲＯＭ（Read Only Memory）、ＨＤＤ（Hard Disk Drive）、フラッシュメモリ等の記憶媒体から構成される。制御部４０は、アカウント管理サーバ３が備えるＣＰＵ（Central Processing Unit）によるプログラム実行処理や、専用回路等により実現される。制御部４０がプログラム実行処理により実現する場合、記憶部３０には、制御部４０の機能を実現するためのプログラムが格納される。
【００２９】
記憶部３０には、アカウント情報ＤＢ３１が格納されている。アカウント情報ＤＢ３１は、各ユーザのアカウント情報が検索可能な状態で格納されているものである。図４にアカウント情報の構成を示す。アカウント情報は、ユーザＩＤ３１ａ、パスワード３１ｂ、ユーザ名３１ｃ、生成物パターン３１ｄで構成されている。
【００３０】
ユーザＩＤ３１ａは、ユーザを識別する情報であり、例えば、数字、英字等の組合せで構成される。パスワード３１ｂは、ユーザが任意に決定した情報であり、例えば、数字、英字等の組合せで構成される。ユーザ名３１ｃは、ユーザの名称を示す情報であり、例えば、漢字、平仮名、片仮名等の組合せで構成される。
【００３１】
生成物パターン３１ｄは、ビルドサーバ４がソースコード（拡張子：「.cpp」等）のビルドを行った場合にユーザが受け取る生成物（オブジェクトファイル等）の種類を示す情報である。詳細は後記するが、ビルドサーバ４は、ソースコードをビルドすると（１）プリプロセッシングされたソースコード（拡張子：「.cpp」等）、（２）オブジェクトファイル（拡張子：「.o」等）、（３）実行可能形式ファイル（拡張子：「.exe」等）のいずれも生成することができる。その為、ユーザは、上記３つの中から希望するものを指定して受け取ることができる。
【００３２】
・パターン「１」は、生成物として「プリプロセッシングされたソースコード」のみの受け取りを希望する場合に設定される。
・パターン「２」は、生成物として「オブジェクトファイル」のみの受け取りを希望する場合に設定される。
・パターン「３」は、生成物として「実行可能形式ファイル」のみの受け取りを希望する場合に設定される。
・パターン「４」は、「プリプロセッシングされたソースコード」と「オブジェクトファイル」の二つの受け取りを希望する場合に設定される。
・パターン「５」は、「プリプロセッシングされたソースコード」と「実行可能形式ファイル」の二つの受け取りを希望する場合に設定される。
・パターン「６」は、「オブジェクトファイル」と「実行可能形式ファイル」の二つの受け取りを希望する場合に設定される。
・パターン「７」は、「プリプロセッシングされたソースコード」と「オブジェクトファイル」と「実行可能形式ファイル」の全ての受け取りを希望する場合に設定される。
【００３３】
続いて、図３に戻り、制御部４０について説明する。制御部４０には、アカウント登録部４１と、アカウント認証部４２とが備えられている。ここでは、各機能の概要のみを説明し、詳細は「オンラインビルドシステムの動作」で後記する。
【００３４】
アカウント登録部４１は、ユーザからの依頼によってアカウントを登録し、登録結果を返信する。ここで、ユーザからの依頼は、ビルドサーバ４を介して行われてもよいし、ユーザ端末２から直接行われてもよい。
【００３５】
アカウント認証部４２は、ビルドサーバ４からの依頼によってアカウントの認証を行い、認証結果をビルドサーバ４に返信する。アカウントの認証は、例えば、ユーザからビルドサーバ４に対してソースコードのビルドの依頼がなされた場合に行う。
【００３６】
＜ビルドサーバ＞
図５を参照して、ビルドサーバ４の機能構成について説明する。ビルドサーバ４は、オンラインでソースコード（拡張子：「.cpp」等）を受信し、ソースコードのビルドを行う装置である。
【００３７】
ビルドサーバ４は、記憶部５０と、制御部６０とを備えて構成される。記憶部５０は、ＲＡＭ（Random Access Memory）、ＲＯＭ（Read Only Memory）、ＨＤＤ（Hard Disk Drive）、フラッシュメモリ等の記憶媒体から構成される。制御部６０は、ビルドサーバ４が備えるＣＰＵ（Central Processing Unit）によるプログラム実行処理や、専用回路等により実現される。制御部６０がプログラム実行処理により実現する場合、記憶部５０には、制御部６０の機能を実現するためのプログラムが格納される。
【００３８】
記憶部５０には、プリプロセッシング情報ＤＢ５１が格納されている。プリプロセッシング情報ＤＢ５１は、プリプロセッシング時にソースコードに追加する追加コード情報を検索可能な状態としたものである。追加コード情報は、バグの作り込みを抑制する情報（作り込み抑制情報）であり、検索コード記述５１ａ、追加コード記述５１ｂ、追加位置５１ｃで構成されている。なお、検索コード記述５１ａに対して、追加コード記述５１ｂおよび追加位置５１ｃが複数登録されていてもよい。
【００３９】
検索コード記述５１ａは、ソースコード内で検索対象となるコードであり、例えば、「new」、「dynamic_cast」、「iterator」等で構成される。追加コード記述５１ｂは、検索コード記述５１ａが存在した場合に、ソースコードに追加するコードの情報である。追加位置５１ｃは、検索コード記述５１ａが存在した場合に、追加コード記述５１ｂを追加するソースコードの位置情報（宣言部も含む）である。詳細は、実施例で説明する。
【００４０】
続いて、図５に戻り、制御部６０について説明する。制御部６０には、アカウント登録要求部６１と、アカウント認証要求部６２と、プリプロセッシング実行部６３と、コンパイル実行部６４と、生成物提供部６５とが備えられている。ここでは、各機能の概要のみを説明し、詳細は「オンラインビルドシステムの動作」で後記する。
【００４１】
アカウント登録要求部６１は、ユーザ端末２からアカウント登録要求を受信した場合に、受信したアカウント登録要求をアカウント管理サーバ３に送信（転送）するものである。また、アカウント登録要求部６１は、アカウント管理サーバ３からアカウント登録結果を受信した場合に、受信したアカウント登録結果をユーザ端末２に送信（転送）するものである。
【００４２】
アカウント認証要求部６２は、ユーザ端末２からアカウント認証要求を受信した場合に、受信したアカウント認証要求をアカウント管理サーバ３に送信（転送）するものである。また、アカウント認証要求部６２は、アカウント管理サーバ３からアカウント認証結果を受信した場合に、受信したアカウント認証結果をユーザ端末２に送信（転送）するものである。
【００４３】
プリプロセッシング実行部６３は、プリプロセッシング情報ＤＢ５１を参照して、ソースコードの中から検索対象のコード記述を検索し、対象の記述が存在した場合に所定のコードをソースコードに追加記述するものである。
【００４４】
コンパイル実行部６４は、プリプロセッシングされたソースコードをコンパイルするものである。コンパイル実行部６４は、ソースコードをコンパイルすると（１）プリプロセッシングされたソースコード（拡張子：「.cpp」等）、（２）オブジェクトファイル（拡張子：「.o」等）、（３）実行可能形式ファイル（拡張子：「.exe」等）のいずれも生成する。
【００４５】
生成物提供部６５は、生成物パターン３１ｄに基づいて、ユーザ端末２に生成物を送信する。
以上で、オンラインビルドシステム１の構成についての説明を終了する。
【００４６】
≪実施形態に係るオンラインビルドシステムの動作≫
オンラインビルドシステム１の動作について説明する。ここでは、まずアカウント登録処理について説明し、続いて、ビルド処理について説明する。オンラインビルドシステム１では、ビルド処理の実行に際して、アカウント登録処理の成功が事前に必要である。
【００４７】
＜アカウント登録処理＞
図７を参照して、オンラインビルドシステム１を利用するユーザのアカウント登録処理について説明する。
最初に、ユーザ端末２のアカウント登録要求部２１は、ビルドサーバ４に対してアカウント登録要求を送信する（ステップＳ１１）。次に、ビルドサーバ４のアカウント登録要求部６１は、アカウント管理サーバ３に対してアカウント登録要求を送信する（ステップＳ１２）。次に、アカウント管理サーバ３のアカウント登録部４１は、アカウント情報を作成し、アカウント情報をアカウント情報ＤＢ３１に登録する（ステップＳ１３）。次に、アカウント管理サーバ３のアカウント登録部４１は、ビルドサーバ４に対してアカウント登録応答を送信する（ステップＳ１４）。次に、ビルドサーバ４のアカウント登録要求部６１は、ユーザ端末２に対してアカウント登録応答を送信する（ステップＳ１５）。
【００４８】
なお、ここでは、アカウント登録処理について説明したが、アカウント更新処理やアカウント削除処理についても同様に行うことが可能である。その場合に、図７に示す「アカウント登録」を「アカウント更新」または「アカウント削除」に読み替えるものとする。
【００４９】
＜ビルド処理＞
図８を参照して、オンラインビルドシステム１のビルド処理について説明する。
最初に、ユーザ端末２のアカウント認証要求部２２は、ビルドサーバ４に対してアカウント認証要求を送信する（ステップＳ２１）。次に、ビルドサーバ４のアカウント認証要求部６２は、アカウント管理サーバ３に対してアカウント認証要求を送信する（ステップＳ２２）。次に、アカウント管理サーバ３のアカウント認証部４２は、アカウント情報ＤＢ３１を参照してアカウント情報を認証する（ステップＳ２３）。次に、アカウント管理サーバ３のアカウント認証部４２は、ビルドサーバ４に対してアカウント認証応答を送信する（ステップＳ２４）。ビルドサーバ４は、ここで、アカウント情報を取得する。次に、ビルドサーバ４のアカウント認証要求部６２は、ユーザ端末２に対してアカウント認証応答を送信する（ステップＳ２５）。なお、ビルドサーバ４によるアカウント情報の取得は、ステップＳ２４のタイミングに限定されるものではない。
【００５０】
次に、ユーザ端末２のビルド要求部２３は、ビルドサーバ４に対してソースコードを送信する（ステップＳ２６）。次に、ビルドサーバ４のプリプロセッシング実行部６３は、受信したソースコードのプリプロセッシングを実行する（ステップＳ２７）。プリプロセッシングの詳細については後記する。次に、ビルドサーバ４のコンパイル実行部６４は、プリプロセッシングしたソースコードのコンパイルを実行する（ステップＳ２８）。次に、ビルドサーバ４の生成物提供部６５は、取得したアカウント情報の生成物パターンに対応する生成物をユーザ端末２に対して送信する（ステップＳ２９）。そして、ユーザは受信した生成物を用いてＵＴを実施する。なお、ステップＳ２６でコンパイルできないソースコードが送信された場合には、ステップＳ２９で生成物提供部６５がユーザ端末２に対してエラー応答を生成物として送信するのがよい。
【００５１】
＜プリプロセッシング処理＞
図９を参照して、ステップＳ２７におけるビルドサーバ４のプリプロセッシング実行部６３のプリプロセッシング処理について説明する。なお、各ステップでのより詳細な処理については、実施例で説明する。
まず、プリプロセッシング実行部６３は、プリプロセッシング情報ＤＢ５１を参照して検索コード記述の検索（パターン検索）を行う（ステップＳ３１）。続いて、プリプロセッシング実行部６３は、ステップＳ３１でソースコード内にパターンが有ったか否かを判定し（ステップＳ３２）、ステップＳ３２で“Ｙｅｓ”の場合に処理をステップＳ３３に進め、ステップＳ３２で“Ｎｏ”の場合に処理を終了する。
【００５２】
ステップＳ３２で“Ｙｅｓ”の場合に、プリプロセッシング実行部６３は、宣言部有りのパターンであるか否かを判定（ステップＳ３３）し、ステップＳ３３で“Ｙｅｓ”の場合に処理をステップＳ３４に進め、ステップＳ３３で“Ｎｏ”の場合に処理をステップＳ３５に進める。ステップＳ３３で“Ｙｅｓ”の場合に、プリプロセッシング実行部６３は、プリプロセッシング情報ＤＢ５１を参照して宣言部にコードを埋め込み（ステップＳ３４）、処理をステップＳ３５に進める。
【００５３】
ステップＳ３３で“Ｎｏ”の場合、およびステップＳ３４に続いて、プリプロセッシング実行部６３は、プリプロセッシング情報ＤＢ５１を参照してパターンの所定場所にコードを埋め込み（ステップＳ３５）、処理を終了する。なお、複数のパターンの検索を行う場合には、ステップＳ３１からステップＳ３５までの処理を繰り返し行う。なお、ステップＳ３４の処理とステップＳ３５の処理とは、順序が逆であってもよい。つまり、パターンの所定場所にコードを埋め込んだ後に、宣言部にコードを埋め込んでもよい。
以上で、オンラインビルドシステム１の動作についての説明を終了する。
【実施例１】
【００５４】
＜DELETE_ARRAY（スカラー配列へのDELETEの使用）＞
実施例１ではソースコードに「DELETE_ARRAY（スカラー配列へのDELETEの使用）」が記述されている場合に、プリプロセッシングで追加するコード記述について説明する。
図１０（ａ）はバグ有りのサンプルコードを示し、図１０（ｂ）はバグ無しのサンプルコードを示している。
【００５５】
図１０（ａ）では、前段で配列のインスタンスを確保したにも関わらず、符号Ｃ１１に示す部分で配列の先頭しか解放されていない。その為、メモリリークの原因となる。
そうならない為には、「new」で配列インスタンスを確保した場合に、図１０（ｂ）の符号Ｃ１２で示すように、必ず「delete」に「[ ]」を記載する必要がある。
【００５６】
プリプロセッシング実行部６３は、ＵＴ工程でユーザがバグの発見をできるように、以下のコード埋め込みを行う。
（１）「new」が記述されているソースファイルを全て検索する。
（２）ファイル内に「new」が記述されている場合、ファイルの先頭に次の３行のコードを埋め込む。
#include<crtdbg.h>
#define _CRTDBG_MAP_ALLOC
#define new ::new(_NORMAL_BLOCK, __FILE__, __LINE__)
（３）「new」が記述されている関数（メソッド）内の末尾（’}’直前の行）に、次の1行を埋め込む。
_CrtDumpMemoryLeaks();
【００５７】
図１０（ｃ）は、図１０（ｂ）のコードに対するプリプロセッシング後のコードを示している。図１０（ｃ）では、符号Ｃ１３に示す部分で「crtdbg.h」を「include」し、「_CRTDBG_MAP_ALLOC」を「define」している。また、符号Ｃ１４に示す部分「_CrtDumpMemoryLeaks()」でログを出力している。その為、ユーザは、図１０（ａ）に示すようにバグが有る場合でも、ＵＴ工程でこのログを確認することにより、図１０（ｂ）に示すコードに修正できる。
【実施例２】
【００５８】
＜FORWARD_NULL（未確認のダイナミックキャスト）＞
実施例２ではソースコードに「FORWARD_NULL（未確認のダイナミックキャスト）」が記述されている場合に、プリプロセッシングで追加するコード記述について説明する。
図１１（ａ）はバグ有りのサンプルコードを示し、図１１（ｂ），（ｃ）はバグ無しのサンプルコードを示している。
【００５９】
図１１（ａ）では、符号Ｃ２１に示す部分で「dynamic_cast」が失敗すると何も返さない（ダウンキャストが保証できないため、NULLのままとなる）。そして、符号Ｃ２２に示す部分で、「NULL」に対してアクセス可能性がある。
そうならない為には、図１１（ｂ）の符号Ｃ２３に示すように、参照するオブジェクトに「const」を付けずダウンキャストを保証してから、符号Ｃ２４に示すようにダイナミックキャストを行うようにする。
または、図１１（ｃ）の符号Ｃ２５に示すように、ダウンキャストが失敗するようであれば、コンパイルに失敗するようにする。
【００６０】
プリプロセッシング実行部６３は、ＵＴ工程でユーザがバグの発見をできるように、以下のコード埋め込みを行う。
（１）「dynamic_cast」が記述されているソースファイルをすべて検索する。
（２）ファイル内に「dynamic_cast」が記述されていた場合、ファイルの先頭に次の２行のコードを埋め込む（宣言部へのコード埋め込み）。
#include<stdio.h>
#include<stdlib.h>
（３）ファイル内に「dynamic_cast」が記述されていた場合、［代入先の変数］を特定する。
（４）「dynamic_cast」記述行の次行に、次の３行のコードを埋め込む。
if( ［代入先の変数］ == NULL ){
fprintf(stderr, “%s”, errMsg); abort();
}
【００６１】
図１２（ｄ）は、図１１（ｂ）のコードに対するプリプロセッシング後のコードを示している（宣言部の記載は省略）。図１２（ｄ）では、符号Ｃ２６に示す部分で「NULLチェック」を行うことで、ダイナミックキャストの成否が分かる。その為、ユーザは、図１１（ａ）に示すようにバグが有る場合でも、ＵＴ工程でダイナミックキャストの成否を判定することにより、図１１（ｂ），（ｃ）に示すコードに修正できる。
【実施例３】
【００６２】
＜INVALIDATE_ITERATOR（不正なイテレータの使用）＞
実施例３ではソースコードに「INVALIDATE_ITERATOR（不正なイテレータの使用）」が記述されている場合に、プリプロセッシングで追加するコード記述について説明する。
図１３（ａ）はバグ有りのサンプルコードを示し、図１３（ｂ），（ｃ），図１４（ｄ）はバグ無しのサンプルコードを示している。
【００６３】
図１３（ａ）では、符号Ｃ３１に示す部分でイテレータが無効化され、符号Ｃ３２に示す部分で無効化されたイテレータを参照している。
そうならない為には、図１３（ｂ）に示すように、符号Ｃ３３に示す部分でイテレータが不要であることを示すフラグを設け、符号Ｃ３４に示す部分でフラグチェックを行うようにする。この方法は、以降の処理でイテレータを使用しない場合に有効である。
【００６４】
または、図１３（ｃ）に示すように、イテレータを後置インクリメントし、符号Ｃ３５に示す部分でイテレータのコピーを「erase()」に渡すようにする。これにより、イテレータは無効化されない。この方法は、以降もイテレータを使用するが、終端ではない場合に有効である。
【００６５】
または、図１４（ｄ）に示すように、符号Ｃ３６に示す部分で有効なイテレータを受け取り、符号Ｃ３７に示す部分で仮の要素を代入している。これにより、イテレータは無効化されない。この方法は、以降もイテレータを使用するが、削除したイテレータの要素について感知しない場合に有効である。
【００６６】
プリプロセッシング実行部６３は、ＵＴ工程でユーザがバグの発見をできるように、以下のコード埋め込みを行う。
（１）イテレータ「iterator」が記述されているソースファイルをすべて検索する。
（２）ファイル内に「iterator」が記述されていた場合、［代入先の変数］を特定する。
（３）ファイル内に次の記述があった場合、
.erase(［代入先の変数］)
代入先の変数の定義箇所を、文字列検索により特定し、下記のようにコピー変数を作成する。なお、作成場所は、eraseが実行されているネスト（カーリブレイス→{}）の先頭に記述する。
typename std::list<T>::iterator new_it = m_lockQueue.begin();
new_it = it;
加えて、erase実施直後に次のif文を追記する。
if( it != new_it ){
fprintf(stderr, “invalid iterator used!\n”);
}
加えて、ファイル先頭に次の１行を埋め込む。（DEBUGMSGを利用せず、fprintfを利用する場合の対処）
#include<stdio.h>
【００６７】
図１４（ｅ）は、図１３（ｃ）のコードに対するプリプロセッシング後のコードを示している（宣言部の記載は省略）。イテレータが無効になるタイミングは「erase()」が実行された場合に限られる。図１４（ｅ）では、符号Ｃ３８に示す部分で新イテレータを新たに定義しなおし、削除処理が実施された後の符号Ｃ３９に示す部分で、旧イテレータと新イテレータとの間で差分があった場合にログを出力する。その為、ユーザは、図１３（ａ）に示すようにバグが有る場合でも、ＵＴ工程でこのログを確認することにより、図１３（ｂ），（ｃ），図１４（ｄ）に示すコードに修正できる。
【実施例４】
【００６８】
＜MISSING_LOCK（データに対する競合）＞
実施例４ではソースコードに「MISSING_LOCK（データに対する競合）」が記述されている場合に、プリプロセッシングで追加するコード記述について説明する。
図１５（ａ）はバグ有りのサンプルコードを示し、図１５（ｂ）はバグ無しのサンプルコードを示している。
【００６９】
図１５（ａ）では、符号Ｃ４１に示す共有変数に対して、符号Ｃ４２に示す部分でロックを取らずにアクセスしているので競合の可能性がある。
そうならない為には、図１５（ｂ）に示すように、共有変数に対して「grep」を行い、共有変数を使用している前の符号Ｃ４３に示す部分でロックを取得し、共有変数を使用している後の符号Ｃ４４に示す部分でロックを解放するようにする。
【００７０】
プリプロセッシング実行部６３は、ＵＴ工程でユーザがバグの発見をできるように、以下のコード埋め込みを行う。
（１）文字列検索等でlock処理が記述されている箇所を特定する。
（２）当該処理の先頭に、以下の記述を追加する。
fprintf (stderr, “locked.\n”);
（３）文字列検索等でunlock処理が記述されている箇所を特定する。
（４）当該処理の先頭に、以下の記述を追加する。
fprintf (stderr, “unlocked.\n”);
（５）ファイル先頭に次の１行を埋め込む（宣言部へのコード埋め込み）。
#include<stdio.h>
【００７１】
図１５（ｃ）は、図１５（ｂ）のコードに対するプリプロセッシング後のコードを示している（宣言部の記載は一部省略）。図１５（ｃ）では、符号Ｃ４５に示す部分でlock関数内にデバッグメッセージを埋め込め、符号Ｃ４６に示す部分でunlock関数内にデバッグメッセージを埋め込む。その為、ユーザは、図１５（ａ）に示すようにバグがある場合でも、共有変数の使用回数と、lock/unlockのデバッグメッセージ表示回数とを確認することにより、図１５（ｂ）に示すコードに修正できる。
【実施例５】
【００７２】
＜NEGATIVE_RETURNS（引数が負の値をとれない）＞
実施例５ではソースコードに「NEGATIVE_RETURNS（引数が負の値をとれない）」が記述されている場合に、プリプロセッシングで追加するコード記述について説明する。
図１６（ａ）はバグ有りのサンプルコードを示し、図１６（ｂ）はバグ無しのサンプルコードを示している。
【００７３】
図１６（ａ）では、符号Ｃ５１で示す部分で負の値を返すことがあり、符号Ｃ５２に示す部分で「memcpy」に負数を渡してしまうと整数オーバーフローを引き起こし、任意コード実行の脆弱性を生み出してしまう。
そうならない為には、図１６（ｂ）に示すように、符号Ｃ５３で「unsigned int(size_t)版」と「signed int(ssize_t)版」を用意する(オーバーロード)。そして、符号Ｃ５４で、安全な「memcpy(s_memcpy)」利用するようにする。なお、memmove, memset, memcmp, strncpy等、整数オーバーフローの危険性がある関数も同様に対処する。
【００７４】
プリプロセッシング実行部６３は、ＵＴ工程でユーザがバグの発見をできるように、以下のコード埋め込みを行う。
（１）「memcpy」が記述されているソースファイルをすべて検索する（memcpy以外についても別途行う）。
（２）ファイル内に「memcpy」が記述されていた場合、「s_memcpy」に置き換える。
（３）ファイル内に「memcpy」が記述されていた場合、 ファイルの先頭に次の７行を埋め込む。
void* s_memcpy(void* dest, const void* src, std::size_t n) __THROW { return std::memcpy(dest, src, n); }
void* s_memcpy(void* dest, const void* src, ssize_t n) { 
if(n < 0) { 
throw std::runtime_error("s_memcpy: integer overflow detected."); 
} 
return s_memcpy(dest, src, (std::size_t)n); 
}
【００７５】
図１７（ｃ）は、図１６（ｂ）のコードに対するプリプロセッシング後のコードを示している。図１７（ｃ）では、符号Ｃ５５に示す部分で負数を返す可能性がある関数については、返値の評価を行っている（走行ルートを分岐している）。その為、ユーザは、図１６（ａ）に示すようにバグがある場合でも、返値の評価を行うことにより、図１６（ｂ）に示すコードに修正できる。
【実施例６】
【００７６】
＜PASS_BY_VALUE（大きなパラメータの値渡し）＞
実施例６ではソースコードに「PASS_BY_VALUE（大きなパラメータの値渡し）」が記述されている場合に、プリプロセッシングで追加するコード記述について説明する。
図１８（ａ）はバグ有りのサンプルコードを示し、図１８（ｂ），（ｃ）はバグ無しのサンプルコードを示している。
【００７７】
図１８（ａ）では、符号Ｃ６１に示す部分で１８４バイトのオブジェクトのコピーが渡されている。一般的に１６バイトを超えるオブジェクトのコピーはコストが高いとされる。
そうならない為には、図１８（ｂ）の符号Ｃ６２や符号Ｃ６３に示すように、インスタンスのポインタを渡すようにする。
または、図１８（ｃ）の符号Ｃ６４に示すように、インスタンスの参照を渡すようにする。
【００７８】
プリプロセッシング実行部６３は、ＵＴ工程でユーザがバグの発見をできるように、以下のコード埋め込みを行う。
（１）デストラクタが記述されているソースファイルをすべて検索する。
（２）ファイル内にデストラクタが記述されていた場合、ファイルの先頭に次の１行を埋め込む（宣言部へのコード埋め込み）。
#define OBJECT_SIZE_LIMIT 16
（３）ファイル内にデストラクタが記述されていた場合、デストラクタ内末尾に次の３行を埋め込む。
if( OBJECT_SIZE_LIMIT < sizeof(*this) ){
DEBUGMSG(“NodeTable memfree = %dbytes\n”, sizeof(*this));
}
【００７９】
図１９（ｄ）は、図１８（ｃ）のコードに対するにプリプロセッシング後のコードを示している（宣言部の記載は省略）。図１９（ｄ）では、符号Ｃ６５に示す部分で、デストラクタに自身のインスタンスサイズを評価する機能を盛り込み、１６バイトを超えるオブジェクトのメモリ解放があれば、デバッグメッセージを出力する。その為、ユーザは、図１８（ａ）に示すようにバグがある場合でも、デバッグメッセージの確認を行うことにより、図１８（ｂ），（ｃ）に示すコードに修正できる。
【実施例７】
【００８０】
＜SIZEOF_MISMATCH（不正なsizeofの引数）＞
実施例７ではソースコードに「SIZEOF_MISMATCH（不正なsizeofの引数）」が記述されている場合に、プリプロセッシングで追加するコード記述について説明する。
図２０（ａ）はバグ有りのサンプルコードを示し、図２０（ｂ）はバグ無しのサンプルコードを示している。
【００８１】
図２０（ａ）では、符号Ｃ７１に示す部分でヒープ領域にメモリ確保したポインタを「sizeof」の引数に渡している為、「sizeof」はポインタのサイズ（4or8）しか返さない。
そうならない為には、図２０（ｂ）の符号Ｃ７２に示すように、実際に確保したサイズと型のサイズを乗じた値を渡すようにする。
【００８２】
プリプロセッシング実行部６３は、ＵＴ工程でユーザがバグの発見をできるように、以下のコード埋め込みを行う。
（１）「memset」が記述されているソースファイルをすべて検索する。
（２）「memset」の第３引数を検出する。
（３）ファイル内に「memset」が記述されていた場合、ファイルの先頭に次のコードを埋め込む（宣言部へのコード埋め込み）。
#include<stdio.h>
（４）「memset」の前後に次のコードを埋め込む。
unsigned int size_t = [第3引数];
if( size_t >= logMsgSize ){
memset(logMsg, 0x0, size_t  );
} else {
fprintf (stderr, “memset size_t invalid = %d\n”, size_t);
}
【００８３】
図２０（ｃ）は、図２０（ｂ）のコードに対するにプリプロセッシング後のコードを示している（宣言部の記載は省略）。図２０（ｃ）では、符号Ｃ７３に示す部分で、「size_t」を利用する関数（memset等）については、「size_t」の引数に直接「sizeof」を利用しないこととし、別途「size_t」のバイト数が配列長よりも大きいか否かの評価を行う。その為、ユーザは、図２０（ａ）に示すようにバグがある場合でも、デバッグメッセージの確認を行うことにより、図２０（ｂ）に示すコードに修正できる。
【実施例８】
【００８４】
＜UNCAUGHT_EXCEPT（キャッチされない例外）＞
実施例８ではソースコードに「UNCAUGHT_EXCEPT（キャッチされない例外）」が記述されている場合に、プリプロセッシングで追加するコード記述について説明する。
図２１（ａ）はバグ有りのサンプルコードを示し、図２１（ｂ）はバグ無しのサンプルコードを示している。
【００８５】
図２１（ａ）では、符号Ｃ８１で示す部分で、定義されていない「boost::lock_error」の例外をスローする。
そうならない為には、図２１（ｂ）の符号Ｃ８２に示すように、発生し得る全ての例外パターンについて、処理を規定する。
【００８６】
プリプロセッシング実行部６３は、ＵＴ工程でユーザがバグの発見をできるように、以下のコード埋め込みを行う。
（１）「Exceptionクラス」が記述されているソースファイルをすべて検索する。
（２）コンストラクタに、次の通りコードを埋め込む。
コンストラクタ(){
std::set_unexpected(unexpected_handler);
}
（３）「Exceptionクラス」内に、次の通りコードを埋め込む。
void unexpected_handler(){
fprintf(stderr, “Called unexpected handler\n”);
throw(expected_handler);
}
（４）ファイルの先頭に次のコードを埋め込む（宣言部へのコード埋め込み）。
#include<stdio.h>
【００８７】
図２２（ｃ）は、図２１（ｂ）のコードに対するにプリプロセッシング後のコードを示している。ＵＴ工程において例外ハンドラはスタブとして用いられるので、図２２（ｃ）の符号Ｃ８３に示す部分で、「unexpected」をユーザのハンドラで上書きし、そこにログを表示するコードを記述している。さらに、ユーザのハンドラで許可（予期）している例外を発生させることで、強制終了（terminated()の発生）を防ぐことができる。その為、ユーザは、図２１（ａ）に示すようにバグがある場合でも、ＵＴでデバッグメッセージの確認を行うことにより、図２１（ｂ）に示すコードに修正できる。
【実施例９】
【００８８】
＜UNINIT_CTOR（スカラー値の未初期化）＞
実施例９ではソースコードに「UNINIT_CTOR（スカラー値の未初期化）」が記述されている場合に、プリプロセッシングで追加するコード記述について説明する。
図２３（ａ）はバグ有りのサンプルコードを示し、図２３（ｂ）はバグ無しのサンプルコードを示している。
【００８９】
図２３（ａ）では、符号Ｃ９１に示すように、コンストラクタでメンバ変数が初期化されておらず、符号Ｃ９２に示すように、初期化されていないメンバ変数値が設定されている。
そうならない為には、図２３（ｂ）の符号Ｃ９３に示すように、コンストラクタ内でメンバ変数を全て初期化する。
【００９０】
プリプロセッシング実行部６３は、ＵＴ工程でユーザがバグの作り込みを抑制するために、以下のコード埋め込みを行う。
（１）コンストラクタに、クラス内で定義されたメンバ変数のうち、未初期化のものをすべて初期化するコードを次のように埋め込む。
クラス(){
private:
メンバ変数1 = 0;
メンバ変数2 = 0;
…
};
【００９１】
図２４（ｃ）は、図２３（ｂ）のコードに対するプリプロセッシング後のコードを示している。図２４（ｃ）の符号Ｃ９４に示す部分では、コンストラクタ内でメンバ変数の初期化忘れ、またはコンストラクタ内で初期値を決定できない場合の対策として初期化フラグを設け、「setter」が呼ばれた時に初期化フラグを「ON」にし、「getter」ではすでに初期化済みか否かを判定する（通常、スカラー値の未初期化はコンパイラのワーニングとして出力される）。その為、ユーザは、図２３（ａ）に示すようにバグがある場合でも、変数の初期化をＵＴ時点で意識することができ、変数の初期化フローを確認する機会が生まれるので、図２３（ｂ）に示すコードに修正できる。
【００９２】
以上のように、実施形態に係るオンラインビルドシステム１は、ソースコード上の脆弱性（バグ）の発見を手助けするコードを自動的に埋め込むことができる。その為、本発明に係るオンラインビルドシステム１は、静的解析ツールを用いて静的リファクタリングを実施することなく、従来、単体試験工程（ＵＴ）で発見が困難とされていたバグをＵＴで発見することができる。
【００９３】
また、実施形態に係るオンラインビルドシステム１は、プリプロセッシングされたコード以外にも、オブジェクトファイルや実行可能形式ファイルを生成することができる。その為、本発明に係るオンラインビルドシステム１は、ユーザの求めに応じて種々の生成物を提供することが可能である。
【００９４】
［変形例］
以上、本発明の実施形態について説明したが、本発明はこれに限定されるものではなく、特許請求の範囲の趣旨を変えない範囲で実施することができる。実施形態の変形例を以下に示す。
【００９５】
実施形態では、アカウント管理サーバ３とビルドサーバ４とを別装置としていた。しかしながら、アカウント管理サーバ３の機能をビルドサーバ４が有する単一の装置であってもよい。また、アカウントの登録・認証を行わなくてもよい。
【００９６】
また、実施形態では、コンパイルをビルドサーバ４で行っていた。しかしながら、ビルドサーバ４以外（例えば、ユーザ端末２）でコンパイルを行ってもよい。
【符号の説明】
【００９７】
１      オンラインビルドシステム
２      ユーザ端末
３      アカウント管理サーバ
４      ビルドサーバ
５０    記憶部
５１    プリプロセッシング情報ＤＢ
６０    制御部
６３    プリプロセッシング実行部
６４    コンパイル実行部
６５    生成物提供部
【図１】
2015197902.tif 000003
【図２】
2015197902.tif 000004
【図３】
2015197902.tif 000005
【図４】
2015197902.tif 000006
【図５】
2015197902.tif 000007
【図６】
2015197902.tif 000008
【図７】
2015197902.tif 000009
【図８】
2015197902.tif 000010
【図９】
2015197902.tif 000011
【図１０】
2015197902.tif 000012
【図１１】
2015197902.tif 000013
【図１２】
2015197902.tif 000014
【図１３】
2015197902.tif 000015
【図１４】
2015197902.tif 000016
【図１５】
2015197902.tif 000017
【図１６】
2015197902.tif 000018
【図１７】
2015197902.tif 000019
【図１８】
2015197902.tif 000020
【図１９】
2015197902.tif 000021
【図２０】
2015197902.tif 000022
【図２１】
2015197902.tif 000023
【図２２】
2015197902.tif 000024
【図２３】
2015197902.tif 000025
【図２４】
2015197902.tif 000026