本發(fā)明涉及一種檢測(cè)方法,尤其涉及一種基于后綴樹的代碼文件克隆檢測(cè)方法。
背景技術(shù):
從軟件產(chǎn)業(yè)的誕生到現(xiàn)在,隨著計(jì)算機(jī)用戶數(shù)量快速增加,軟件產(chǎn)業(yè)發(fā)展迅猛,已滲透到人們工作與生活的方方面面。許多軟件源代碼開放在互聯(lián)網(wǎng)上,開發(fā)人員在互聯(lián)網(wǎng)查詢所需要的相關(guān)代碼已成為一種快速有效的生產(chǎn)方式。由于共同的軟件功能,經(jīng)過簡單修改或者直接的復(fù)制粘貼,代碼重用已經(jīng)是軟件開發(fā)中一個(gè)通用行為。開源代碼的快速發(fā)展,上百萬的軟件工程源代碼在相關(guān)網(wǎng)絡(luò)上可以查找,如googlecodesearch,github,snippir,sourceforge,github等,今天開源代碼已經(jīng)在軟件發(fā)展中處于重要地位。隨之而來的現(xiàn)象就是,無論有意或無意的復(fù)制開源代碼,軟件系統(tǒng)存在代碼段與其他代碼非常相似,也稱之為代碼克隆。在一般的軟件系統(tǒng)中都存在明顯代碼克隆部分,代碼相似比例在7%-23%。
代碼克隆通常是有目的性的,可以減輕開發(fā)人員重復(fù)性工作,專注核心功能研發(fā)等,從這些方面來說是有用的。但是也存在許多問題不利于軟件的維護(hù)和擴(kuò)展。例如,在一個(gè)代碼段中存在漏洞,所有相似的代碼段都應(yīng)該被檢測(cè)出相同漏洞。特別是直接使用開源代碼,沒有任何風(fēng)險(xiǎn)意識(shí)的人員也將開源代碼的問題帶入開發(fā)的軟件系統(tǒng)。這些產(chǎn)品應(yīng)用在國防、醫(yī)療、金融等重要領(lǐng)域,給工作帶來巨大的潛在風(fēng)險(xiǎn)。
在大型軟件系統(tǒng)中,代碼的雷同、抄襲現(xiàn)象頻發(fā),人們維權(quán)意識(shí)增強(qiáng),一些代碼克隆侵犯了其他軟件公司的知識(shí)產(chǎn)權(quán)。為保護(hù)軟件產(chǎn)權(quán),軟件公司提前做好軟件技術(shù)秘密的認(rèn)定、保密措施,申請(qǐng)專利權(quán)、軟件著作權(quán)登記。但是在發(fā)生侵權(quán)行為后,需要對(duì)軟件產(chǎn)品進(jìn)行判定,以維護(hù)自己的權(quán)利,這對(duì)兩方公司都產(chǎn)生嚴(yán)重影響。
無意識(shí)的代碼克隆使軟件產(chǎn)品引入外部風(fēng)險(xiǎn),可以依賴代碼克隆檢測(cè),在軟件開發(fā)過程中得到避免或警示。一方面根據(jù)開源代碼公布的漏洞,代碼克隆檢測(cè)出所有漏洞,可以讓開發(fā)人員認(rèn)識(shí)存在的問題,對(duì)風(fēng)險(xiǎn)進(jìn)行識(shí)別再?zèng)Q定是否使用開源代碼。另一方面,也能了解軟件系統(tǒng)使用非自主開發(fā)代碼情況,評(píng)估該軟件產(chǎn)品的技術(shù)含量。
還存在許多其他的軟件工程任務(wù)需要代碼克隆檢測(cè),如程序理解,了解克隆代碼領(lǐng)域知識(shí);代碼質(zhì)量分析,較少的克隆可能意味著更好的代碼質(zhì)量;對(duì)軟件進(jìn)行演化分析;分析代碼重復(fù)程度,對(duì)代碼進(jìn)行壓縮;根據(jù)代碼來源進(jìn)行代碼病毒檢測(cè)以及代碼錯(cuò)誤檢測(cè)。而軟件開發(fā)基于計(jì)算機(jī)語言,語言結(jié)構(gòu)簡單,比自然語言更易被機(jī)器識(shí)別。軟件工程任務(wù)需要能夠自主進(jìn)行代碼克隆檢測(cè)的工具,識(shí)別克隆代碼的漏洞、知識(shí)產(chǎn)權(quán)、授權(quán)許可等信息。并且與一般文本的自然語言克隆檢測(cè)不同,根據(jù)不同類型的代碼克隆,代碼克隆有一定規(guī)律性,也更適合自動(dòng)檢測(cè)。
現(xiàn)在代碼克隆檢測(cè)研究都是基于兩個(gè)代碼段間進(jìn)行比對(duì),實(shí)際無法提前知道該軟件復(fù)制哪些代碼源,需要將代碼與大量代碼進(jìn)行匹配檢測(cè),對(duì)于檢測(cè)效率有更高的要求。而使用開源代碼是直接導(dǎo)入整個(gè)開源項(xiàng)目,若進(jìn)行代碼內(nèi)容匹配則花費(fèi)更多時(shí)間。本專利在代碼克隆檢測(cè)對(duì)象上,由一對(duì)一向一對(duì)多進(jìn)行,分析不同克隆情況并開發(fā)檢測(cè)工具,進(jìn)行實(shí)際應(yīng)用。
有鑒于上述的缺陷,本設(shè)計(jì)人,積極加以研究創(chuàng)新,以期創(chuàng)設(shè)一種基于后綴樹的代碼文件克隆檢測(cè)方法,使其更具有產(chǎn)業(yè)上的利用價(jià)值。
技術(shù)實(shí)現(xiàn)要素:
為解決上述技術(shù)問題,本發(fā)明的目的是提供一種基于后綴樹的代碼文件克隆檢測(cè)方法。
本發(fā)明的基于后綴樹的代碼文件克隆檢測(cè)方法,其中:對(duì)工程項(xiàng)目文件構(gòu)造后綴樹,在線性時(shí)間內(nèi)實(shí)現(xiàn)代碼文件克隆檢測(cè),其包括以下步驟:
步驟一,構(gòu)造開源項(xiàng)目指紋庫,采用的后綴樹為ukkonen算法,
步驟二,對(duì)代碼文件克隆進(jìn)行檢測(cè),
若從指紋庫中直接檢索相同的文件指紋,整個(gè)檢測(cè)實(shí)現(xiàn)的算法復(fù)雜度為o(mn),m為待檢測(cè)項(xiàng)目的文件指紋數(shù),n是指紋庫的指紋數(shù);
以后綴樹方法為基礎(chǔ),完成在線性時(shí)間內(nèi)檢測(cè)相同代碼文件。
進(jìn)一步地,上述的基于后綴樹的代碼文件克隆檢測(cè)方法,其中,所述步驟一中,
代碼文件為粒度構(gòu)造代碼指紋,所述代碼指紋直接保存在主服務(wù)器上,建立指紋庫和代碼克隆檢測(cè);
用戶輸入相關(guān)信息并上傳開源工程項(xiàng)目,或是選擇直接從網(wǎng)絡(luò)上進(jìn)行自動(dòng)抓取,對(duì)開源工程項(xiàng)目解壓并存放到指定目錄,遍歷開源項(xiàng)目,對(duì)符合用戶輸入語言的代碼文件進(jìn)行處理;
根據(jù)用戶輸入的最小文件行數(shù)對(duì)較少行數(shù)的代碼文件進(jìn)行過濾,通過md5哈希得到指紋值,并將指紋保存到mysql數(shù)據(jù)庫中。
更進(jìn)一步地,上述的基于后綴樹的代碼文件克隆檢測(cè)方法,其中,所述步驟一中,以代碼文件自定義對(duì)象的序列作為節(jié)點(diǎn)內(nèi)容,自定義對(duì)象filenode結(jié)構(gòu)如表所示,
文件粒度指紋庫保存在mysql數(shù)據(jù)庫的t_file_hash表中,
更進(jìn)一步地,上述的基于后綴樹的代碼文件克隆檢測(cè)方法,其中,所述步驟一中,將開源工程項(xiàng)目添加到指紋庫中,遍歷該工程項(xiàng)目,對(duì)符合條件的代碼文件采用jflex進(jìn)行詞法分析過濾,并md5哈希。
更進(jìn)一步地,上述的基于后綴樹的代碼文件克隆檢測(cè)方法,其中,采用的算法括構(gòu)建后綴樹和遞歸處理剩余后綴節(jié)點(diǎn)兩部分,構(gòu)造后綴樹的偽代碼表,
對(duì)兩個(gè)工程項(xiàng)目構(gòu)成的filenode序列構(gòu)造后綴樹,遍歷序列每個(gè)對(duì)象,如果后綴樹中存在當(dāng)前對(duì)象指紋值為前綴的后綴,則改變?nèi)M和剩余后綴數(shù)的值,否則直接添加到當(dāng)前節(jié)點(diǎn)的子節(jié)點(diǎn);
對(duì)于已經(jīng)保存的待插入剩余后綴,直到遍歷到不存在以當(dāng)前對(duì)象為前綴的后綴節(jié)點(diǎn),則需要對(duì)后綴樹進(jìn)行分裂;
分裂活動(dòng)中,將活動(dòng)節(jié)點(diǎn)的filenode序列以活動(dòng)長度作為分裂點(diǎn),前半部分作為活動(dòng)節(jié)點(diǎn)的序列,后半部分添加到其子節(jié)點(diǎn),并且將當(dāng)前剩余序列添加到活動(dòng)節(jié)點(diǎn)的子節(jié)點(diǎn);
分裂完成后按照三個(gè)規(guī)則處理三元組,最后按照剩余插入后綴數(shù)遞歸處理待插入的filenode序列。
更進(jìn)一步地,上述的基于后綴樹的代碼文件克隆檢測(cè)方法,其中,所述步驟一中,對(duì)ukkonen算法進(jìn)行適應(yīng)性優(yōu)化,將后綴樹構(gòu)造應(yīng)用到代碼文件克隆檢測(cè)中,包括,
d)序列節(jié)點(diǎn),每次插入新對(duì)象時(shí),構(gòu)造的新節(jié)點(diǎn)內(nèi)容為對(duì)象序列,而不是單個(gè)對(duì)象;
e)節(jié)點(diǎn)標(biāo)記,在構(gòu)造后綴樹過程中及時(shí)標(biāo)記公共子串所在的節(jié)點(diǎn);
減少比較,掃描一個(gè)新文件對(duì)象時(shí),查找是否存在以該文件相同指紋值的對(duì)象為開頭的后綴節(jié)點(diǎn)時(shí),對(duì)標(biāo)記為不可能是克隆文件的節(jié)點(diǎn)不進(jìn)行比較。
更進(jìn)一步地,上述的基于后綴樹的代碼文件克隆檢測(cè)方法,其中,每次插入新節(jié)點(diǎn)時(shí),節(jié)點(diǎn)內(nèi)容是以該字符為起始位置到結(jié)束的序列,
檢測(cè)兩個(gè)filenode序列的克隆代碼文件,在兩個(gè)項(xiàng)目序列中間添加標(biāo)識(shí)符標(biāo)識(shí)一個(gè)項(xiàng)目的結(jié)束,而在構(gòu)造過程中,若一個(gè)非葉節(jié)點(diǎn)的子節(jié)點(diǎn)中含有這個(gè)標(biāo)識(shí)符,則說明這個(gè)非葉節(jié)點(diǎn)的filenode對(duì)象既在檢測(cè)任務(wù)中出現(xiàn)也在開源項(xiàng)目中出現(xiàn),為兩個(gè)項(xiàng)目的克隆代碼文件。
再進(jìn)一步地,上述的基于后綴樹的代碼文件克隆檢測(cè)方法,其中,所述步驟二中,進(jìn)行克隆度和相似度計(jì)算,
根據(jù)后綴樹構(gòu)造過程中保存的克隆結(jié)果進(jìn)行統(tǒng)計(jì)計(jì)算,檢測(cè)項(xiàng)目的克隆度指該項(xiàng)目有克隆開源項(xiàng)目的代碼文件行數(shù)占所有代碼文件行數(shù)和的比值,定義如公式1所示,fi是檢測(cè)項(xiàng)目克隆文件,fj是檢測(cè)項(xiàng)目代碼文件,line表示該文件的行數(shù),
相似度,指檢測(cè)項(xiàng)目與一個(gè)開源項(xiàng)目的相似度,檢測(cè)項(xiàng)目與開源項(xiàng)目克隆的文件行數(shù)占兩個(gè)項(xiàng)目所有代碼文件行數(shù)和的比值,定義如公式2所示,fi是檢測(cè)項(xiàng)目克隆文件,pi是開源項(xiàng)目克隆文件,fj是檢測(cè)項(xiàng)目代碼文件,pj是開源項(xiàng)目代碼文件,line表示該文件的行數(shù),
借由上述方案,本發(fā)明能在線性時(shí)間內(nèi)檢測(cè)出克隆的代碼文件,比直接按照指紋值進(jìn)行檢測(cè)有更高效率,實(shí)現(xiàn)海量檢測(cè)。
上述說明僅是本發(fā)明技術(shù)方案的概述,為了能夠更清楚了解本發(fā)明的技術(shù)手段,并可依照說明書的內(nèi)容予以實(shí)施,以下以本發(fā)明的較佳實(shí)施例并配合附圖詳細(xì)說明如后。
附圖說明
圖1是構(gòu)建文件粒度指紋庫流程圖。
圖2是代碼克隆來源分析系統(tǒng)流程圖。
具體實(shí)施方式
下面結(jié)合附圖和實(shí)施例,對(duì)本發(fā)明的具體實(shí)施方式作進(jìn)一步詳細(xì)描述。以下實(shí)施例用于說明本發(fā)明,但不用來限制本發(fā)明的范圍。
如圖1、圖2的基于后綴樹的代碼文件克隆檢測(cè)方法,其是對(duì)工程項(xiàng)目文件指紋構(gòu)造后綴樹,在線性時(shí)間內(nèi)實(shí)現(xiàn)代碼文件克隆檢測(cè),采用如下步驟:
步驟一,構(gòu)造開源項(xiàng)目指紋庫。
以代碼文件為粒度構(gòu)造代碼指紋,指紋數(shù)量可控,占用存儲(chǔ)空間有限,因此可以直接保存在主服務(wù)器上。實(shí)現(xiàn)本發(fā)明的后臺(tái)主要完成兩個(gè)功能,建立指紋庫和代碼克隆檢測(cè)。具體來說,用戶輸入相關(guān)信息并上傳開源工程項(xiàng)目或者選擇直接從網(wǎng)絡(luò)上進(jìn)行自動(dòng)抓取,對(duì)開源工程項(xiàng)目解壓并存放到指定目錄,遍歷開源項(xiàng)目,對(duì)符合用戶輸入語言的代碼文件進(jìn)行處理。同時(shí),可以根據(jù)用戶輸入的最小文件行數(shù)對(duì)較少行數(shù)的代碼文件進(jìn)行過濾,不少于設(shè)置行數(shù)的代碼文件進(jìn)行詞法分析過濾,并md5哈希得到指紋值,并將指紋保存到mysql數(shù)據(jù)庫中。
本發(fā)明所設(shè)計(jì)的文件粒度指紋庫保存在mysql數(shù)據(jù)庫的t_file_hash表中,表的具體信息如表1所示。因?yàn)槲募6戎讣y是以一個(gè)文件為對(duì)象,所有指紋存儲(chǔ)數(shù)據(jù)簡單,最核心字段代碼文件指紋值hash。為了確定是哪個(gè)開源工程項(xiàng)目工程文件則需要保存路徑location。開源工程項(xiàng)目id的設(shè)計(jì)是由于克隆檢測(cè)時(shí),后綴樹檢測(cè)以兩個(gè)工程項(xiàng)目的指紋序列為基礎(chǔ),需要按工程項(xiàng)目檢索指紋值。為此,在該表中不需要為指紋值hash建立數(shù)據(jù)庫索引,而是為了能夠快速按照工程項(xiàng)目進(jìn)行檢索,在創(chuàng)建表時(shí)候?qū)ψ侄蝡rojectid建立索引。
表1t_file_hash表。
在此期間,將開源工程項(xiàng)目添加到指紋庫中,遍歷該工程項(xiàng)目,對(duì)符合條件的代碼文件采用jflex進(jìn)行詞法分析過濾,并md5哈希。應(yīng)用本發(fā)明的系統(tǒng)使用的md5算法是使用java.security.messagedigest定義的算法。這是一個(gè)單向散列函數(shù),任意長度的字符序列生成固定長度的證書。為了方便處理和提高比較效率,將md5獲得的128位長整數(shù),對(duì)處理得到32位的十六進(jìn)制哈希值。
步驟二,代碼文件克隆檢測(cè)如果使用從指紋庫中直接檢索相同的文件指紋,整個(gè)檢測(cè)實(shí)現(xiàn)的算法復(fù)雜度為o(mn)。其中,m為待檢測(cè)項(xiàng)目的文件指紋數(shù),n是指紋庫的指紋數(shù)。在實(shí)際實(shí)施期間,為了實(shí)現(xiàn)相同的目標(biāo),并且提高算法效率,lp代碼文件克隆檢測(cè)算法以后綴樹方法為基礎(chǔ),能夠完成在線性時(shí)間內(nèi)檢測(cè)相同代碼文件。
結(jié)合本發(fā)明一較佳的實(shí)施方式來看,本發(fā)明在實(shí)施期間所提出的檢測(cè)算法基礎(chǔ)是后綴樹ukkonen算法,其以代碼文件自定義對(duì)象的序列作為節(jié)點(diǎn)內(nèi)容,自定義對(duì)象filenode結(jié)構(gòu)如表1所示。
具體來說,采用filenode表示一個(gè)代碼文件的指紋對(duì)象,即工程項(xiàng)目文件的hash值。filenode序列相當(dāng)于字符串序列,filenode的指紋值相當(dāng)于字符的值,通過構(gòu)造filenode序列的后綴樹將文件檢測(cè)轉(zhuǎn)換為文件對(duì)象的“字符串”檢測(cè)。為了有效檢測(cè)兩個(gè)字符串的公共子串,在兩個(gè)字符串的中間添加一個(gè)唯一的不會(huì)在字符串中出現(xiàn)的字符作為標(biāo)識(shí),后綴樹節(jié)點(diǎn)中根據(jù)這個(gè)標(biāo)識(shí)來判斷某個(gè)非葉節(jié)點(diǎn)是否是公共子串。
同時(shí),在filenode序列后綴樹的構(gòu)造過程中,以比較指紋值相等與否來確定兩個(gè)filenode對(duì)象是否存在克隆關(guān)系,并在待檢測(cè)工程項(xiàng)目序列結(jié)尾添加一個(gè)hash值為#的filenode對(duì)象為標(biāo)識(shí)。
由于開源工程項(xiàng)目代碼文件數(shù)量較多,不可能一次性構(gòu)造用戶項(xiàng)目和所有開源項(xiàng)目構(gòu)成的filenode序列后綴樹,并且開源工程項(xiàng)目之間也存在代碼克隆關(guān)系,一次性構(gòu)造也可能產(chǎn)生許多不必要結(jié)果。所以,將待檢測(cè)工程項(xiàng)目和一個(gè)開源工程項(xiàng)目得到的filenode序列構(gòu)造后綴樹,得到其“公共子串”也就是克隆的代碼文件,實(shí)現(xiàn)代碼文件的克隆檢測(cè)。遍歷所有開源工程項(xiàng)目,就完成了檢測(cè)。
例如:用戶檢測(cè)任務(wù)有4個(gè)文件n(i),開源工程項(xiàng)目有3個(gè)文件m(i),加上項(xiàng)目標(biāo)識(shí)符#和結(jié)束標(biāo)識(shí)符$構(gòu)成9個(gè)filenode對(duì)象的序列,對(duì)該序列構(gòu)造后綴樹也在圖中顯示。序列后綴樹中除了根節(jié)點(diǎn),存在兩個(gè)非葉節(jié)點(diǎn),并且這兩個(gè)非葉節(jié)點(diǎn)都存在含有#標(biāo)識(shí)符的葉子節(jié)點(diǎn),說明這兩個(gè)節(jié)點(diǎn)是公共子串,也就是兩個(gè)工程項(xiàng)目的克隆代碼文件。
n(i)表示待檢測(cè)工程項(xiàng)目文件的filenode,m(i)表示開源工程項(xiàng)目文件filenode,f表示filenode序列,該序列:n(1)n(2)…n(n)#m(1)m(2)…m(m)$。以f為輸入構(gòu)造后綴樹,后綴樹的每個(gè)葉子節(jié)點(diǎn)是以$為結(jié)尾的f子序列,每個(gè)非葉節(jié)點(diǎn)是f的子序列且有三種形式:n(i)…n(j)、n(i)…n(n)#m(1)…m(j)和m(i)…m(j)。如果n(i)和m(j)是克隆文件,則在f構(gòu)造的后綴樹中存在某個(gè)非葉節(jié)點(diǎn),且該節(jié)點(diǎn)的子序列中存在n(i)文件的filenode。
結(jié)合算法中核心變量三元組(活動(dòng)節(jié)點(diǎn),活動(dòng)邊,活動(dòng)長度)來看,其中中,節(jié)點(diǎn)是后綴樹的節(jié)點(diǎn),剩余后綴數(shù)指已經(jīng)遍歷過待插入的filenode數(shù)。判斷某個(gè)filenode是否已經(jīng)在后綴樹中存在以該文件為開頭的后綴,是根據(jù)三元組直接進(jìn)行判斷,以filenode的hash值是否相等判斷filenode相等與否。
以本發(fā)明實(shí)施期間的算法實(shí)現(xiàn)來看,主要包括構(gòu)建后綴樹和遞歸處理剩余后綴節(jié)點(diǎn)兩部分,構(gòu)造后綴樹的偽代碼如表2所示。
對(duì)兩個(gè)工程項(xiàng)目構(gòu)成的filenode序列構(gòu)造后綴樹,遍歷序列每個(gè)對(duì)象,如果后綴樹中存在當(dāng)前對(duì)象指紋值為前綴的后綴,則改變?nèi)M和剩余后綴數(shù)的值,否則直接添加到當(dāng)前節(jié)點(diǎn)的子節(jié)點(diǎn)。對(duì)于已經(jīng)保存的待插入剩余后綴,直到遍歷到不存在以當(dāng)前對(duì)象為前綴的后綴節(jié)點(diǎn),則需要對(duì)后綴樹進(jìn)行分裂。分裂活動(dòng)邊,將活動(dòng)節(jié)點(diǎn)的filenode序列以活動(dòng)長度作為分裂點(diǎn),前半部分作為活動(dòng)節(jié)點(diǎn)的序列,后半部分添加到其子節(jié)點(diǎn),并且將當(dāng)前剩余序列添加到活動(dòng)節(jié)點(diǎn)的子節(jié)點(diǎn)。分裂完成后按照三個(gè)規(guī)則處理三元組,最后按照剩余插入后綴數(shù)遞歸處理待插入的filenode序列。
表2lp代碼文件克隆檢測(cè)后綴樹構(gòu)造算法偽代碼。
根據(jù)剩余后綴數(shù)插入之前未插入的filenode,遞歸調(diào)用處理函數(shù)innersplit,直到filenode都被處理,分裂遞歸處理算法innersplit的偽代碼如表3所示。與構(gòu)造后綴樹的算法處理流程相同,只需要把當(dāng)前處理節(jié)點(diǎn)由當(dāng)前輸入的filenode變成當(dāng)前剩余插入的filenode,按照規(guī)則更改三元組變量,遞歸調(diào)用直到剩余后綴數(shù)變量rest為0。
表3分裂遞歸處理算法偽代碼。
本發(fā)明在實(shí)施期間,還對(duì)ukkonen算法進(jìn)行了適應(yīng)性優(yōu)化。
將后綴樹構(gòu)造應(yīng)用到代碼文件克隆檢測(cè)中,為了提高算法效率,主要做了三點(diǎn)優(yōu)化:
f)序列節(jié)點(diǎn)。每次插入新對(duì)象時(shí),構(gòu)造的新節(jié)點(diǎn)內(nèi)容為對(duì)象序列,而不是單個(gè)對(duì)象。
g)節(jié)點(diǎn)標(biāo)記。在構(gòu)造后綴樹過程中及時(shí)標(biāo)記公共子串所在的節(jié)點(diǎn)。
h)減少比較。掃描一個(gè)新文件對(duì)象時(shí),查找是否存在以該文件相同指紋值的對(duì)象為開頭的后綴節(jié)點(diǎn)時(shí),對(duì)標(biāo)記為不可能是克隆文件的節(jié)點(diǎn)不進(jìn)行比較。
具體來說:
第一個(gè)優(yōu)化,在ukkonen算法中,每次插入新的字符時(shí),若后綴樹中不存在該字符的后綴,則插入新節(jié)點(diǎn),節(jié)點(diǎn)內(nèi)容是該字符。在代碼文件克隆檢測(cè)后綴樹算法中,每次插入新節(jié)點(diǎn)時(shí),節(jié)點(diǎn)內(nèi)容是以該字符為起始位置到結(jié)束的序列。ukkonen算法是不需要事先知道輸入字符串所有內(nèi)容,使用增量方式構(gòu)造后綴樹,構(gòu)造過程中采用壓縮方式存儲(chǔ)了后綴樹。
但是,在代碼文件克隆檢測(cè)中,要構(gòu)造后綴樹時(shí)已經(jīng)事先知道完整的filenode序列。為此,每次插入新節(jié)點(diǎn)時(shí)可以考慮不要修改已有的后綴樹節(jié)點(diǎn)。由此算法設(shè)計(jì)在后綴樹構(gòu)造時(shí),每次插入新節(jié)點(diǎn)時(shí)以當(dāng)前節(jié)點(diǎn)為開始的剩余的filenode序列。
特別是在代碼工程項(xiàng)目中,一個(gè)項(xiàng)目里存在相同的代碼文件情況較少,克隆檢測(cè)構(gòu)造的后綴樹大多數(shù)情況下只有三層,除了克隆的代碼文件外其他都是葉子節(jié)點(diǎn)。若直接使用ukkonen算法,對(duì)葉子節(jié)點(diǎn)的擴(kuò)展會(huì)成為一個(gè)較大的開銷,算法做了這樣的優(yōu)化后則會(huì)減少擴(kuò)展的操作避免開銷。
第二個(gè)優(yōu)化,首先后綴樹解決字符串問題,非葉節(jié)點(diǎn)表示字符串中重復(fù)的子串。檢測(cè)兩個(gè)filenode序列的克隆代碼文件,也就是檢測(cè)出構(gòu)造這個(gè)兩個(gè)序列合并序列的后綴樹中的部分非葉節(jié)點(diǎn)。之所以說是部分非葉節(jié)點(diǎn),因?yàn)榇嬖谝粋€(gè)代碼項(xiàng)目中有兩個(gè)相同文件的情況,這些文件構(gòu)成的節(jié)點(diǎn)也是非葉節(jié)點(diǎn)。為了保證結(jié)果的準(zhǔn)確性,在兩個(gè)項(xiàng)目序列中間添加標(biāo)識(shí)符標(biāo)識(shí)一個(gè)項(xiàng)目的結(jié)束,而在構(gòu)造過程中,若一個(gè)非葉節(jié)點(diǎn)的子節(jié)點(diǎn)中含有這個(gè)標(biāo)識(shí)符,則說明這個(gè)非葉節(jié)點(diǎn)的filenode對(duì)象既在檢測(cè)任務(wù)中出現(xiàn)也在開源項(xiàng)目中出現(xiàn),也就是兩個(gè)項(xiàng)目的克隆代碼文件。
第三個(gè)優(yōu)化,在按順序掃描一個(gè)新文件對(duì)象時(shí),要在后綴樹中查找是否存在以該文件相同指紋值的對(duì)象為開頭的節(jié)點(diǎn)。在ukkonen算法中,需要對(duì)活動(dòng)節(jié)點(diǎn)對(duì)應(yīng)的子節(jié)點(diǎn)全部遍歷以查找。在本算法的實(shí)際應(yīng)用情況中,對(duì)于被標(biāo)記為不可能是克隆文件的節(jié)點(diǎn)可以不進(jìn)行比較,因?yàn)閺?之后的filenode是待檢測(cè)項(xiàng)目自己的文件,肯定不是克隆文件,所以對(duì)這些節(jié)點(diǎn)都可以忽略,可有效提高算法效率。
步驟三,進(jìn)行克隆度和相似度計(jì)算。
根據(jù)后綴樹構(gòu)造過程中保存的克隆結(jié)果進(jìn)行統(tǒng)計(jì)計(jì)算。檢測(cè)項(xiàng)目的克隆度指該項(xiàng)目有克隆開源項(xiàng)目的代碼文件行數(shù)占所有代碼文件行數(shù)和的比值。定義如公式1所示,fi是檢測(cè)項(xiàng)目克隆文件,fj是檢測(cè)項(xiàng)目代碼文件,line表示該文件的行數(shù)。
相似度指檢測(cè)項(xiàng)目與一個(gè)開源項(xiàng)目的相似度,檢測(cè)項(xiàng)目與開源項(xiàng)目克隆的文件行數(shù)占兩個(gè)項(xiàng)目所有代碼文件行數(shù)和的比值。定義如公式2所示,fi是檢測(cè)項(xiàng)目克隆文件,pi是開源項(xiàng)目克隆文件,fj是檢測(cè)項(xiàng)目代碼文件,pj是開源項(xiàng)目代碼文件,line表示該文件的行數(shù)。
通過上述的文字表述并結(jié)合附圖可以看出,采用本發(fā)明后,檢測(cè)實(shí)現(xiàn)能在線性時(shí)間內(nèi)檢測(cè)出克隆的代碼文件,比直接按照指紋值進(jìn)行檢測(cè)有更高效率,實(shí)現(xiàn)海量檢測(cè)。
以上所述僅是本發(fā)明的優(yōu)選實(shí)施方式,并不用于限制本發(fā)明,應(yīng)當(dāng)指出,對(duì)于本技術(shù)領(lǐng)域的普通技術(shù)人員來說,在不脫離本發(fā)明技術(shù)原理的前提下,還可以做出若干改進(jìn)和變型,這些改進(jìn)和變型也應(yīng)視為本發(fā)明的保護(hù)范圍。