Transcript Document

ソースコード流用の
コードクローンメトリクスに基づく検出手法
†奈良先端科学技術大学院大学
情報科学研究科
‡大阪大学 大学院情報科学研究科
○岡原聖† 真鍋雄貴‡ 山内寛己†
門田暁人† 松本健一†
知能ソフトウェア工学研究会
背景
• 近年,オープンソースソフトウェア(OSS)を流用した
ソフトウェア開発が増えている
– 開発コストの低減,高信頼性の確保
• 開発の外注等によりOSSのソースコードが意図せず
混入し,ライセンス違反を犯してしまうケースがある
– Microsoftが外注したWindows7へのUpgrade支援ツール[1]
– SCEIが開発したPS2ゲーム「ICO」のライブラリ[2]
出荷前にソースコード流用の有無を
検出する技術が必要とされている
[1]: “「USB版Windows 7」作成ツールにGPLコード Microsoftが謝罪”,
http://www.itmedia.co.jp/news/articles/0911/16/news026.html
[2]: “PlayStation 2 Game ICO Violates the GPL”, http://news.slashdot.org/article.pl?sid=07/11/28/0328215
知能ソフトウェア工学研究会
2
ソースコード流用とコードクローン
• 流用したコードはコードクローン(以下クローン)
として表れる
コードの流用
流用先のソフトウェア
流用元のOSS
コードクローン(重複するコード列)
知能ソフトウェア工学研究会
3
ソースコード流用検出の難しさ
• クローンは独立に開発されたソフトウェア間でも
存在する
– 定型処理,偶然の一致など
流用の事実はない
GUI生成の
定型処理
GUI生成の
どの程度の量のクローンが検出されたならば
定型処理
流用とみなせるかを明らかにする必要がある
1.クローンの量を測るメトリクスが必要
出荷するソフトウェア
OSS
2.メトリクス値について流用とみなす基準値が必要
コードクローン(重複するコード列)
知能ソフトウェア工学研究会
4
研究目的,アプローチ
• 研究目的
– クローンの量によりソースコード流用の有無を
判断する方法を確立する
• 任意の2つのソフトウェア間で,一方が他方のソースコードを
流用しているか否かを定量的に判断する
• アプローチ
– 2つのクローンメトリクスを提案する
• 最大クローン長
• 部分類似度
– 各メトリクスの流用と見なす基準値(閾値)を求める
• 多数のOSSを用いて実験的に求める
知能ソフトウェア工学研究会
5
本研究で用いるクローン
• クローンの種類
– Exact Clone
完全一致のクローン
– Renamed Clone
変数名や空行の不一致を許容するクローン
– Gapped Clone
コードの削除,追加を許容するクローン
流用後に変数名や定数名などを
変更することがありえるため
知能ソフトウェア工学研究会
6
Renamed Cloneの検出方法
• トークン解析
プログラム言語の字句規則に従いトークンに分割する
• トークン変換
変数(p),定数(i),型(t) 種類毎にトークンを置換する
• マッチング
一致する部分列をクローンとする
...
y=0
x=y
if ( x
z=0
...
;
- z ;
>0 ) n=1 ;
;
-----------------------------------------------------------------------
------------------------------------------------------------------------------
知能ソフトウェア工学研究会
...
}
x=b - c ;
if ( x > 0 ) n = 0 ;
while ( b > 0 ) {
...
7
Renamed Cloneの検出方法
• トークン解析
プログラム言語の字句規則に従いトークンに分割する
• トークン変換
変数(p),定数(i),型(t) 種類毎にトークンを置換する
• マッチング
一致する部分列をクローンとする
...
y=0
x=y
if ( x
z=0
...
;
- z ;
>0 ) n=1 ;
;
-----------------------------------------------------------------------
------------------------------------------------------------------------------
知能ソフトウェア工学研究会
...
}
x=b - c ;
if ( x > 0 ) n = 0 ;
while ( b > 0 ) {
...
8
Renamed Cloneの検出方法
• トークン解析
プログラム言語の字句規則に従いトークンに分割する
• トークン変換
変数(p),定数(i),型(t) 種類毎にトークンを置換する
• マッチング
一致する部分列をクローンとする
...
y = 0i
p
p
x=p
y
if ( p
x
pz = 0i
...
;
- pz ;
> 0i ) p
n = 1i ;
;
-----------------------------------------------------------------------
------------------------------------------------------------------------------
知能ソフトウェア工学研究会
...
}
p
x=p
b - pc ;
if ( p
x > 0i ) p
n = 0i ;
while ( p
b > 0i ) {
...
9
Renamed Cloneの検出方法
• トークン解析
プログラム言語の字句規則に従いトークンに分割する
• トークン変換
変数(p),定数(i),型(t) 種類毎にトークンを置換する
• マッチング
一致する部分列をクローンとする
...
p
y = 0i
p
x=p
y
if ( p
x
pz = 0i
...
;
- pz ;
> 0i ) p
n = 1i ;
;
-----------------------------------------------------------------------
------------------------------------------------------------------------------
知能ソフトウェア工学研究会
...
}
p
x=p
b - pci ;
if ( p
x > 0i ) p
n = 0i ;
while ( p
b > 0i ) {
...
10
流用検出のためのクローンメトリクス(1)
最大クローン長[3]
• 定義
– 検出されたクローンで最大のトークン数
最大クローン
ファイル群 A
最大クローン長
ファイル群 B
• 最大クローン長と流用の関係
– 最大クローン長が大きい:流用の可能性は高い
– 最大クローン長が小さい:流用の可能性は低い
[3]:岡原 聖, 真鍋 雄貴, 山内 寛己, 門田 暁人, 松本 健一, 井上 克郎, “コードクローンの長さに基づくプログラム盗用確率の
実験的算出,” 信学技報, No.SS2008-40, pp.7-11, Oct. 2008.
知能ソフトウェア工学研究会
11
流用検出のためのクローンメトリクス(2)
部分類似度
• 定義
– 最大クローンを含むファイルにのみ着目した類似度
算出式
ファイルの長さ
|a|
2  MLCC
PSim 
|a||b|
ファイルの長さ
|b|
最大クローン長
MLCC
ファイル全体を流用していなくとも,
部分的な流用が存在すると部分類似度は大きくなる
ファイル群A
ファイル群B
知能ソフトウェア工学研究会
12
流用の判断方法
検出されるクローン
は流用ではない
検出されるクローン
は流用である
290
1.多数のソフトウェアを集めて正解集合を作成する
2.正解集合を用いて実験的に閾値を求める
(例:最大クローン長)
270
250
230
210
190
170
150
130
110
90
70
これらの閾値は理論的に求めることは不可能
流用なし閾値
流用あり閾値
50
1,0
0,9
0,8
0,7
0,6
0,5
0,4
0,3
0,2
0,1
0,0
30
流用の割合
• 閾値を超えるクローンを流用あり(流用なし)と
判断する
クローンメトリクスの大きさ
知能ソフトウェア工学研究会
13
閾値の決定方法
• 閾値は必ず流用あり(流用なし)と判断できるもの:
false-positiveなし
– 適合率,再現率を用いて閾値を導出
• 適合率
– 検出結果中に含まれる正検出の割合を示す指標
• 再現率
– 正解集合のうち,どの程度正検出できたかを示す指標
適合率が 1 かつ 再現率が最大値となる
各メトリクスの値を閾値とする
知能ソフトウェア工学研究会
14
閾値の導出実験
• 実験目的
– 流用の判断基準となる閾値を,
多数のOSSを用いて実験的に導出する
• 実験環境
– クローン検出ツール
• CCFinderX[4]
– 実験対象のソフトウェア
• 50件のOSS
• ドメイン:Security, Audio, Game など
• 開発言語:C言語,C++
[4]: “CCFinderホームページ”, http://www.ccfinder.net/ccfinderx-j.html
知能ソフトウェア工学研究会
15
閾値の導出における実験手順
1. 50件のOSSを用いて,正解集合を作成する
–
プログラムの構造,コメント文,クローンの内容などから判断した
組合わせの分類
組合せ件数
ソースコード流用ありの組合せ
121
ソースコード流用なしの組合せ
648
クローンのない組合せ
456
2. OSSの全ての組合せにおいてクローンを検出する
3. 最大クローン長,部分類似度を算出する
4. 流用あり(流用なし)の適合率,再現率をそれぞれ算出する
知能ソフトウェア工学研究会
16
閾値の導出結果
• 流用あり(最大クローン長)
1.0
0.9
0.8
0.7
0.5
適合率
0.4
再現率
0.3
0.2
0.1
290
270
250
230
210
190
170
150
130
110
90
70
50
0.0
30
割合
0.6
流用あり閾値
流用ありの閾値(最大クローン長)
知能ソフトウェア工学研究会
17
閾値の導出結果
• 流用なし(最大クローン長)
1,0
0,9
0,8
0,7
0,5
適合率
0,4
再現率
0,3
0,2
0,1
290
270
250
230
210
190
170
150
130
110
90
70
50
0,0
30
割合
0,6
流用なしの閾値(最大クローン長)
流用なし閾値
知能ソフトウェア工学研究会
18
閾値の導出結果
• 流用あり(部分類似度)
1.0
0.9
0.8
0.7
0.5
0.4
0.3
適合率
0.2
0.1
1.00
0.90
0.80
0.70
0.60
0.50
0.40
0.30
0.20
0.0
0.10
再現率
0.00
割合
0.6
流用あり閾値
流用ありの閾値(部分類似度)
知能ソフトウェア工学研究会
19
閾値の導出結果
• 流用なし(部分類似度)
1.0
0.9
0.8
0.7
0.5
0.4
0.3
適合率
0.2
0.1
1.00
0.90
0.80
0.70
0.60
0.50
0.40
0.30
0.10
0.0
0.20
再現率
0.00
割合
0.6
流用なしの閾値(部分類似度)
流用なし閾値
知能ソフトウェア工学研究会
20
閾値の導出結果
最大クローン長
流用あり
部分類似度
流用あり
最大クローン長
流用なし
部分類似度
流用なし
検出できた件数
91
72
421
-
検出できなかった件数
30
49
227
-
総件数
121
648
• 流用あり閾値
– 両メトリクスとも半数以上の流用を検出できている
• 流用なし閾値
– 部分類似度の流用なし閾値を導出できなかった
2つのメトリクスを併用して流用を検出することで
検出割合が向上するかを確認する
知能ソフトウェア工学研究会
21
追実験の結果
最大クローン長
流用あり
部分類似度
流用あり
最大クローン長
流用なし
部分類似度
流用なし
検出できた件数
91
72
421
-
検出できなかった件数
30
49
227
-
総件数
121
648
• 結果
– 最大クローン長で検出できなかった30件の流用のうち,
11件を流用として検出できた
作成した流用あり正解集合121件のうち,
102件(約84%)をfalse-positiveなしで検出できた
知能ソフトウェア工学研究会
22
メトリクスを併用して検出できた流用
/* Splice in "list" into "head" */
static inline void glame_list_splice(struct glame_list_head
*list, struct glame_list_head *head)
{
struct glame_list_head *first = list->next;
/*
* Splice in "list" into "head"
*/
static INLINE void list_splice(struct list_head *list,
struct list_head *head)
{
struct list_head *first = list->next;
if (first != list) {
struct glame_list_head *last = list->prev;
struct glame_list_head *at = head->next;
if (first != list) {
struct list_head *last = list->prev;
struct list_head *at = head->next;
first->prev = head;
head->next = first;
first->prev = head;
head->next = first;
last->next = at;
at->prev = last;
last->next = at;
at->prev = last;
}
}
}
}
ファイル長さ:141
ファイル長さ:223
最大クローン長 59,部分類似度 0.32
知能ソフトウェア工学研究会
23
まとめ,今後の課題
• まとめ
ソースコード流用のクローンメトリクスを用いた
検出手法を提案した
– 最大クローン長と部分類似度の流用あり閾値,
流用なし閾値を導出した
– 流用あり閾値を用いて約84%の流用を
false-positiveなしで検出できた
• 今後の課題
流用あり(流用なし)検出の精度向上を目指す
– 他のクローンメトリクスを調査する
知能ソフトウェア工学研究会
24
知能ソフトウェア工学研究会
25
知能ソフトウェア工学研究会
26
関連研究
• コードクローンを用いた手法:JPlag[4]
– クローンに基づいた「ソースコード間の類似度」を用いる
クローン
ファイル群 A
ファイル群 B
• Jplagの問題点
– ソースコードの一部分だけを利用する流用を,
流用ありと判断することが難しい
[4]: L. Prechelt, G. Malpohl, and M.Philippsen, “Finding Plagiarisms among a Set of Programs with JPlag,” J.Universal
Computer Science, vol.8, no.11, pp.1016-1038, Nov. 2002.
知能ソフトウェア工学研究会
27
関連研究
• バースマークを用いた手法
– バースマークとは
クラスの継承関係,クラスの出現回数,クラスの実行順序
などのプログラムの特徴量
– バースマークを併用して流用(盗用)の検出を行う
• バースマークの問題点
– 流用の検出を行う者(PM,品質管理実施者など)が
定性的に判断する必要がある
• 一意に決定することが困難である
– ソフトウェア全体での判断になる
[5]:玉田 春昭, 神崎 雄一郎, 中村 匡秀, 門田 暁人, 松本 健一, ``Java クラスファイルからプログラム指紋を抽出する方法の
提案'', 信学技報 情報セキュリティ研究会, Vol. ISEC2003-29, pp.127--133, July 2003.
知能ソフトウェア工学研究会
28
本研究の使用用途
• ソフトウェアの開発委託元が,
開発委託先で流用を行っていないかの確認
• 学生の演習課題でコピーアンドペーストを
行っていないかの確認
• 民事裁判での証拠
– 裁判では互いの資料提出があるため,コードクローンを
利用することは可能
知能ソフトウェア工学研究会
29
人手によるコスト
• ソフトウェア間でクローン検出を行うと,
多数のクローンが検出される
– コストが非常に高いことが予想される
目安となる閾値が存在することで,
人手による判断を行うクローンを減少出来る
知能ソフトウェア工学研究会
30
ソースコード流用による損害賠償
• CAおよび1999年にCAが買収した米PLATINUM
technology Internationalで勤務経験のあるプログラマや
ソフトウエア開発者を雇用して盗用を行う
– 賠償内容)
約2億ドルの損害賠償および恒久的差し止めを求める(継続中)
• Mark ZuckerbergがConnectUの知的財産権およびコードを
盗んでこの巨大人気ソーシャルネットワークを構築
– 賠償内容)
約6500万ドルの損害賠償を受け取る
知能ソフトウェア工学研究会
31
検出できなかった流用
if (size == 0)
return NULL; /* No allocation required. */
if (size == 0)
return NULL; /* no allocation required */
/* Allocate combined header + user data storage. */
{
register pointer new = malloc (sizeof (header) + size);
/* address of header */
/* Allocate combined header + user data storage. */
{
register pointer new = malloc (sizeof (header) +
size);
/* Address of header. */
((header *)new)->h.next = last_alloca_header;
((header *)new)->h.deep = depth;
((header *) new)->h.next = last_alloca_header;
((header *) new)->h.deep = depth;
last_alloca_header = (header *)new;
last_alloca_header = (header *) new;
/* User storage begins just after header. */
/* User storage begins just after header. */
return (pointer)((char *)new + sizeof(header));
}
return (pointer) ((char *) new + sizeof (header));
}
ファイル長さ:636
ファイル長さ:1191
最大クローン長 78,部分類似度 0.085
知能ソフトウェア工学研究会
32