專利名稱:發(fā)現(xiàn)受許可證約束的軟件代碼的制作方法
背景技術(shù):
開放源軟件是公眾能夠免費(fèi)獲取來研究、使用、甚至修改的源代碼或程序。這種代碼在公眾和軟件開發(fā)者之間免費(fèi)共享。由于該軟件不是私有的,所以大批編程者能夠修改并完善該源代碼。經(jīng)修改的軟件被再發(fā)布給公眾和其它編程者,以供廣泛的軟件應(yīng)用。
通常,開放源軟件不是商業(yè)開發(fā)并為了贏利而發(fā)布的,原因在于源代碼是免費(fèi)的。然而,與此同時,軟件常常受到許可證形式的約束。開放源許可證使得用戶能夠獲得免費(fèi)的源代碼,但是提供了能夠限制源代碼使用、修改和再發(fā)布的條款。這樣的限制根據(jù)許可證的不同而變化,并且其范圍從無限制的到完全限制的。例如,一些許可證僅僅要求用戶保持原作者的姓名或者在實(shí)際源代碼中包括版權(quán)聲明。相對比而言,例如,其它許可證嚴(yán)格限制后續(xù)用戶控告專利侵權(quán)、收集派生作品特許權(quán)以及為軟件的修改版本授予許可證的權(quán)力。
由于一些開放源許可證能夠是完全限制的,軟件開發(fā)者和公司在把重要資源投入使用或修改源代碼之前,必須復(fù)審并理解許可證的條款和條件。然而,該任務(wù)是非常困難的,原因在于代碼能夠包括一個或更多的受未知許可證約束的函數(shù)。作為一個例子,編程者能夠在不承認(rèn)管理原始函數(shù)的許可證的情況下,修改或重用函數(shù)并且接著釋放該函數(shù)。例如,最初在一個許可證下釋放的函數(shù)在沒有許可證或者沒有參考原始許可證的情況下被重用并釋放。作為另一個例子,當(dāng)私有代碼受到一個或多個許可證的約束時,能夠像開放源那樣被重用或分類。此外,非私有代碼或開放源代碼能夠隨私有軟件發(fā)布并由此違反開放源許可證。
軟件代碼的各部分能夠由此受到一個或多個許可證的約束,即使這樣的許可證不是隨代碼再生的或以代碼為參考的。為了發(fā)現(xiàn)這樣的許可證,人們可以嘗試人工復(fù)審所有的源代碼并將其與已知受到一個許可證約束的代碼相比較。在假設(shè)代碼的增殖、修改以及遍及世界的發(fā)布的情況下,該任務(wù)將是困難甚至不可能完成的。
圖1是根據(jù)本發(fā)明一個示例性實(shí)施例的確定代碼是否受到一個或多個軟件許可證的約束的示例性流程圖。
圖2是根據(jù)本發(fā)明一個示例性實(shí)施例的確定兩個函數(shù)是否相似的示例性流程圖。
圖3A是根據(jù)本發(fā)明一個示例性實(shí)施例的比對(alignment)算法的第一示圖。
圖3B是根據(jù)本發(fā)明一個示例性實(shí)施例的比對算法的第二示圖。
圖3C是根據(jù)本發(fā)明一個示例性實(shí)施例的比對算法的第三示圖。
圖3D是根據(jù)本發(fā)明一個示例性實(shí)施例的比對算法的第四示圖。
圖3E是根據(jù)本發(fā)明一個示例性實(shí)施例的比對算法的第五示圖。
圖4是根據(jù)本發(fā)明的示例性計算機(jī)系統(tǒng)的模塊圖。
具體實(shí)施例方式
根據(jù)本發(fā)明的實(shí)施例針對用于發(fā)現(xiàn)軟件文件是否與一個或多個許可證相關(guān)聯(lián)或者受到一個或多個許可證約束的設(shè)備、系統(tǒng)和方法。分析代碼(例如源代碼或編譯對象)的一部分或者該代碼中的函數(shù),以確定其是否是受到一個或多個許可證約束的代碼的相似派生品或修改。示例性實(shí)施例快速并準(zhǔn)確地識別受到一個或多個軟件許可證約束的代碼,即使這樣的許可證沒有包括于所述代碼或者由所述代碼為參考也是這樣。即使文件包括超過數(shù)萬行的代碼,依然能在代碼中識別受到許可證約束的函數(shù)。這樣的識別自動發(fā)生而只需很少或完全無需人為干預(yù)。
在一個示例性實(shí)施例中,復(fù)審一個或多個文件以確定這樣的文件是否受到任何許可證或其它限制條款和條件的約束或被其所管理。文件的數(shù)目能夠從一個文件到數(shù)十萬個不同文件而變化。每個文件最初被分為一個或多個函數(shù)。所述函數(shù)被用于檢查某些或特定術(shù)語的出現(xiàn)。這樣的術(shù)語被普通術(shù)語所替代。每個函數(shù)接著被變換為一組標(biāo)志(token)。對應(yīng)于每個函數(shù)的標(biāo)志被與對應(yīng)于已知或預(yù)先存在的許可函數(shù)的標(biāo)志組相比較。換言之,源函數(shù)的標(biāo)志被與來自受到一個或者多個許可證的約束的已知函數(shù)的標(biāo)志相比較。這種比較顯示了源或候選函數(shù)與已知函數(shù)之間的相關(guān)性。確定是否存在匹配。如果存在匹配,則所述源函數(shù)(就像已知函數(shù)一樣)被一個或多個預(yù)先存在或已知的軟件許可證所管理。
在一個示例性實(shí)施例中,一種比對矩陣將源或候選函數(shù)與已知函數(shù)相比較。特別地,所述矩陣將兩個符號序列互相比較。所述符號序列是從各個函數(shù)的標(biāo)志組中得出的。系統(tǒng)確定兩個序列是否類似(即相似)。該確定的結(jié)果被記錄到日志中、保存和/或向用戶輸出。
圖1是根據(jù)本發(fā)明一個示例性實(shí)施例的確定代碼是否受到一個或多個軟件許可證的約束的流程圖100。根據(jù)模塊110,接收或者獲取一個或多個文件(稱為候選、目標(biāo)或源文件)或代碼。所述代碼包括源代碼、編譯對象和可執(zhí)行代碼,但是并不局限于此。例如,所述文件能夠作為一個或多個軟件發(fā)布包來進(jìn)行發(fā)布。候選文件的數(shù)目從一個文件到數(shù)十萬個文件而分布,例如在開放源軟件包或開放源軟件發(fā)布中存在的文件。
在這個時刻,確定是否任何目標(biāo)文件是預(yù)先檢查過的。在一個示例性實(shí)施例中,每個包和檔案文件均被檢查并與預(yù)先檢查文件的知識基礎(chǔ)(knowledge-bases)相比較。例如,如果一個包的特定版本的源代碼已被處理過,則所述代碼不會被再次處理,原因在于所述包的結(jié)果是預(yù)先確定的。
目標(biāo)文件能夠被“打包(packed)”或存檔并且包括一個或多個嵌套或壓縮格式的其他文件。每個包和存檔文件被遞歸地解包直至不需要(例如,用數(shù)據(jù)、可執(zhí)行代碼和文本文件)進(jìn)一步解包為止。對被解包的原始文件的參考被保存和記憶。在一個示例性實(shí)施例中,許多不同的文件格式是已知的或被用于遞歸解包。例如,這樣的文件格式包括zip、tar、ar、cpio、gzip、bzip2、rpm、deb、rar、jar、cabinet文件、postscript以及uuencode/uudecode等,但并不局限于此。如果存檔文件包含其它文件,則其被遞歸地解壓縮和解包。一旦確定再沒有文件需要解包,則解包終止。
根據(jù)模塊120,代碼或目標(biāo)文件被劃分或分割為函數(shù)。如此處所使用的,“函數(shù)”是執(zhí)行特定任務(wù)的程序或代碼的一部分。函數(shù)能夠返回一個值,或者執(zhí)行一個操作但不返回值。根據(jù)編程語言,函數(shù)具有不同的名字,例如子例程、方法、過程或子程序。此外,不同文件格式具有不同的方式來識別函數(shù)(例如,C語言中函數(shù)的符號與對象代碼中的符號不同)。
根據(jù)模塊130,每個函數(shù)中的一個或多個特定術(shù)語被一個或多個普通術(shù)語所替代。例如,每個函數(shù)中的所有變量(即標(biāo)示數(shù)量的符號或符號表示)被單詞“variable”或“var”或其它普通術(shù)語所替代。如另一個示例,每個函數(shù)中的所有數(shù)字被單詞“number”或“num”或其它普通術(shù)語所替代。
根據(jù)模塊140,每個函數(shù)被變換為一個或多個標(biāo)志。如此處所使用的,詞語“標(biāo)志”表示文本、字符或具有含義的符號的分類塊。例如,標(biāo)志由不可分割的字符或語義(lexeme)組成。語義根據(jù)一個函數(shù)被讀取和分類并且被提供一個含義,該過程稱為“標(biāo)志化(tokenization)”。如此處所使用的,詞語“標(biāo)志化”表示將輸入字符的串的一個或多個部分劃分界限并分類的過程。
根據(jù)模塊130和140,根據(jù)特定的文件格式,函數(shù)被以不同的方式標(biāo)志化。如所述,變量名被術(shù)語“variable”所替代并且術(shù)語“variable”在此后被看作一個關(guān)鍵詞標(biāo)志。此外,數(shù)字被術(shù)語“number”所替代,并且術(shù)語“number”在此后被看作一個關(guān)鍵詞標(biāo)志。標(biāo)志化能夠基于語言特定的關(guān)鍵詞(例如,“if”或者“while”)、符號(例如,+、=、-、<、>等)和范圍(例如,()、{}、[]等)而發(fā)生。例如,函數(shù)“a+b=b+7”具有標(biāo)志“var+var=var+num”。如另一個示例,“call function(9)”具有標(biāo)志“call var(num)”。此外,在一個示例性實(shí)施例中,標(biāo)志的值不相關(guān)。
根據(jù)模塊150,從目標(biāo)函數(shù)中得出的標(biāo)志被與來自已知函數(shù)的標(biāo)志相比較。在一個示例性實(shí)施例中,已知函數(shù)包括受到一個或多個許可證約束或由其所管理的代碼。
在一個示例性實(shí)施例中,獲取或發(fā)現(xiàn)已知的或預(yù)先存在的軟件許可證,例如開放源軟件許可證。開放源文件受到數(shù)千個不同許可證的約束。這些許可證中的許多可以經(jīng)互聯(lián)網(wǎng)在開放源軟件發(fā)布包中例如通過利用免費(fèi)和開放源軟件(Free and Open Source Software,F(xiàn)OSS)的組織并通過提倡開放源的組織獲得。每個已知許可證具有一個或多個受一個或多個許可證的約束或被其所管理的文件。從而得知這些文件中的代碼具有每個許可證的特定約束或限制。
如結(jié)合模塊120所討論的,一旦獲取了已知文件,所述文件被劃分為函數(shù)。如結(jié)合模塊130所討論的,函數(shù)中的某些術(shù)語被普通術(shù)語所替代。如結(jié)合模塊140所討論的,所述函數(shù)接著變換為一個或多個標(biāo)志。
在這個時刻,至少存在兩個不同的標(biāo)志組或序列。第一組標(biāo)志對應(yīng)于目標(biāo)函數(shù)(即,確定其是否受到已知許可條款的約束的函數(shù))。第二組標(biāo)志對應(yīng)于比較或已知函數(shù)(即,預(yù)先已知受到軟件許可證約束或受到限制條款和/或條件約束的函數(shù))。模塊150比較這兩組標(biāo)志序列。
根據(jù)模塊160。確定在對應(yīng)于目標(biāo)函數(shù)的標(biāo)志和對應(yīng)于比較或已知函數(shù)的標(biāo)志之間是否存在匹配。在一個示例性實(shí)施例中,為每一對函數(shù),計算比對矩陣。識別所述比對矩陣中的最大值,并且確定是否存在匹配。例如,如果目標(biāo)函數(shù)和比較函數(shù)之間的相似性或共性滿足或超過一個閾值(例如,70%、80%或其它預(yù)先設(shè)定的值),則存在匹配。
根據(jù)模塊170,把來自模塊160的結(jié)果記錄到日志中并保存。在一個示例性實(shí)施例中,將結(jié)果提供給用戶(例如,作為報告輸出到顯示器,等等)。在一個示例性實(shí)施例中,把滿足或超過一個閾值或具有預(yù)先定義的相似性的匹配記錄到日志(例如,存儲目標(biāo)和已知函數(shù)的名稱、匹配百分比、匹配和/或不匹配的確切標(biāo)志,等等)。
圖2是根據(jù)本發(fā)明一個示例性實(shí)施例的確定兩個函數(shù)是否相似的示例性流程圖200。結(jié)合圖3A-3E(示出一系列示圖,所述視圖用于圖示確定一個或多個源或候選函數(shù)是否受到一個或多個已知或預(yù)先存在的許可證的約束的示例性實(shí)施例)來討論圖2。示例中的每個不同字母表示一個不同的標(biāo)志。使用符號比對矩陣將兩個符號序列相互比較,并且確定這樣的序列是否相似。
根據(jù)模塊210,為源函數(shù)和比較函數(shù)計算一個或多個標(biāo)志。該階段在圖1中的模塊110-140更為詳細(xì)的討論。
在一個示例性實(shí)施例中,比較編譯對象的兩個部分以確定它們是否可能為來自相同源代碼的派生品。該比較基于兩個假設(shè)(1)相同的源代碼產(chǎn)生相同的操作代碼,和(2)相同的操作代碼序列由相同的源代碼所創(chuàng)建。例如,當(dāng)兩個不同的軟件開發(fā)者獨(dú)立地創(chuàng)建了相同的功能性,它們的源代碼很可能是唯一的并生成唯一的操作代碼序列。當(dāng)代碼被用作模板,所述代碼通常具有相似的表現(xiàn)形式,但卻生成不同的操作代碼序列。相對比而言,當(dāng)源代碼被再次使用(例如,借用、修改、被平衡(leveraged)、復(fù)制,等等),存在少量修改,但是主要功能元素保持相同。由于在此后一種情形中的代碼主要是相同或等同的,所以所述代碼生成相似的操作代碼序列。根據(jù)本發(fā)明的實(shí)施例識別相似代碼和類似功能性的部分或片斷。
根據(jù)本發(fā)明的實(shí)施例能夠利用一個或多個假設(shè)以分析代碼,并確定候選代碼和代碼之間是否存在相似性。這樣的假設(shè)包括以下幾種宏、內(nèi)聯(lián)代碼、編譯器最優(yōu)化、代碼重排序和軟件開發(fā)者,但并不局限于此。宏能夠啟動或禁止不同的代碼片斷,特別是留在源代碼中的調(diào)試語句。標(biāo)示為“內(nèi)聯(lián)”的函數(shù)通常直接插入函數(shù)中。這些函數(shù)能夠改變操作代碼序列,但是卻未必改變源代碼的樣子。關(guān)于編譯器最優(yōu)化,不同的編譯器選項(xiàng)將操作代碼序列修改為更好或最佳性能。關(guān)于代碼重排序,如果兩個代碼片斷S1和S2在源代碼文件A中以[S1,S2]出現(xiàn),而在不同的源代碼文件B中以[S2,S1]出現(xiàn),則根據(jù)本發(fā)明的實(shí)施例識別最大比對(如果|s1|>|s2|,則僅識別S1)。
如所注意的,還進(jìn)行關(guān)于軟件開發(fā)者的假設(shè)。雖然這些假設(shè)能夠?qū)е洛e誤消極匹配,但是認(rèn)為下列用于軟件開發(fā)者的假設(shè)中的一個或多個是有效的。第一,開發(fā)者通常重新使用函數(shù)和非代碼的單獨(dú)行。第二,開發(fā)者可以對函數(shù)做少量改變,而不是對這樣的函數(shù)做顯著改變(顯著改變典型地導(dǎo)致重新開發(fā)而不是重新使用)。第三,開發(fā)者通常不對重新使用的代碼中的成分重排序。最后,開發(fā)者通常使用相似的編譯選項(xiàng)。例如,大多數(shù)內(nèi)核驅(qū)動器開發(fā)者對于相同的平臺使用相同的編譯器和編譯器標(biāo)記。
為了舉例起見,比較A列表和B列表的兩個序列。這兩個列表均包含符號序列(串)。每個列表的長度分別標(biāo)示為|A|和|B|。比對矩陣(表示于圖3A-3E)標(biāo)示為A×B。矩陣位置(a,b)表示A[a]和B[b]在A×B中的交叉點(diǎn)。
一個示例性實(shí)施例確定A中的符號與B中的符號對準(zhǔn)的百分比,以及B中的符號與A中的符號對準(zhǔn)的百分比。這些百分比標(biāo)示為A*B和B*A。例如,如果A*B為60%,則A中60%的符號與B中的符號對準(zhǔn)。A*B和B*A很可能不同,除非A和B完全相同并具有相同長度。
當(dāng)兩個序列在相似順序上具有相似元素時,所述兩個序列是類似的。類似性是一個兩個序列是類似的或者是不類似的定性描述(這樣,在一個示例性實(shí)施例中,不存在“60%類似”的值)。與之相比,相似性是一個定量描述。兩個序列可以是60%相似的,并且也可以被認(rèn)為是類似的。類似性定義相似性的閾值。此外,類似性是不對稱的。換句話說,當(dāng)B不類似于A時,A能夠類似于B。當(dāng)|B|比|A|大時能夠發(fā)生該情形。再此外,子集能夠是類似的。例如,A可能不類似于B,但是子集“a”卻有可能類似于“b”。
在一個示例性實(shí)施例中,系統(tǒng)假設(shè)相似的序列產(chǎn)生相似的功能性。該概念隨符號存在,例如源代碼行或反編譯的操作代碼序列。根據(jù)本發(fā)明的實(shí)施例由此允許比較平臺獨(dú)立的序列。
在一個示例性實(shí)施例中,比對算法使用下列三個階段或步驟中的一個或多個初始化、同等識別(identical identification)和比對。這三個階段表示于圖3A-3E。
根據(jù)模塊220,為源函數(shù)和比較函數(shù)計算比對矩陣。該階段結(jié)合圖3A和3B圖示。
圖3A示出比對算法的最初的或初始化階段。最初,把符號或序列對準(zhǔn)在矩陣中。為了舉例,為A選擇符號“cheloe”,為B選擇符號“hello”。如所示,A的符號(cheloe)被垂直排列于矩陣上,而B的符號(hello)被水平排列于矩陣上。矩陣的每個單元最初為空白或者0。
圖3B示出同等識別階段。在此,如果A[a]與B[b]相同,則矩陣A×B中的每個位置標(biāo)記為“1”。如果A[a]與B[b]不相同,則該單元或矩陣坐標(biāo)為空白(或標(biāo)記為“0”)。這樣,圖3B示出A[a]與B[b]相同的六個不同位置(即,(2,1)、(3,2)、(4,3)、(4,4)、(5,5)和(6,2))。
根據(jù)模塊230,在比對矩陣中識別出最大值。接著,根據(jù)模塊240,如果在源函數(shù)和比較函數(shù)之間存在相似性,則識別出匹配。在一個示例性實(shí)施例中,此相似性至少部分地基于一個或多個閾值。圖3C-3E示出模塊230和240的比對階段。
首先,如圖3C所示,矩陣中的每個單元被更新為其自身與子矩陣[(0,0),(a-1,b-1)]中最大值之和。這樣,表元素(3,3)在圖3B中最初為0或空白。然而,在圖3C中,此表元素(即,對應(yīng)于字母“l(fā)”和“e”)被更新為值1,原因在于子表[(0,0),(1,1)]中的最大值為1。相似地,代表“l(fā)”דl(fā)”的表元素(2,3)獲得值3。對于單元(2,3)等同+max[(0,0),(1,2)]=1+2=3。
圖3D示出矩陣中的每個單元更新為其自身與子矩陣[(0,0),(a-1,b-1)]中最大值之和后的最終表。如所示,外邊緣上的最大值(即,4)表示已對準(zhǔn)的字符的最大數(shù)目。這樣,就有4個已對準(zhǔn)的字符。
圖3E示出最佳對準(zhǔn)路徑。特別地,分配給最大值的單元(沿箭頭所示)表示最佳對準(zhǔn)路徑。在該示例中,所述路徑表示(1)“4”來自于“o”;(2)“3”來自于“l(fā)”(即,對于“hello”僅有兩種選擇,而對于“cheloe”有一種選擇);(3)“2”來自于“e”(“cheloe”中的第一個“e”);和(4)“1”來自于“h”。水平和垂直間隙確切地示出那些符號對準(zhǔn)(1)“cheole”與“_helo_”對準(zhǔn),和(2)“hello”與“hel_o”或“he_lo”對準(zhǔn)(如圖所示)。此外,對于對準(zhǔn)的百分比(1)“cheloe”與“hello”的80%對準(zhǔn)(即,4/5符號),和(2)“hello”與“cheloe”的67%對準(zhǔn)(即4/6符號)。
如果|A|要比|B|大得多,則B很可能具有相對大的百分比,而A則具有相對低的百分比。如果A和B都是非平凡的(即,都相對大)并且都具有高相似度,則它們很可能互為變量。例如,閾值80%表示序列被重用并且由此對應(yīng)于受一個或多個許可證約束的已知或預(yù)先存在的函數(shù)。
根據(jù)本發(fā)明實(shí)施例的示例性實(shí)施例比較單個字母或符號。例如,如果串是同樣的,則認(rèn)為兩個元素是相同的。在一個實(shí)施例中,所述串是來自于代碼(例如源代碼、反編譯的匯編代碼等)的行。
根據(jù)模塊250,相似的匹配被記錄入到日志、存儲和/或提供給用戶。在比較之后,存在一個匹配列表。該列表示出詳細(xì)的匹配(例如,下至函數(shù)級別)并提供一個或多個概要、范圍、模式等。所述日志可包括與多個標(biāo)志之間的極端匹配。小標(biāo)志能夠包括十二個或更少標(biāo)志。較大的標(biāo)志可包括數(shù)百或數(shù)千個標(biāo)志。從而,匹配能夠包括幾個標(biāo)志或數(shù)千個標(biāo)志。在一個示例性實(shí)施例中,當(dāng)匹配標(biāo)志的總數(shù)(來自所有函數(shù)比較)大于特定閾值時(例如,大于一千個標(biāo)志),所有的文件被識別為匹配。
所述日志還可包括與多個函數(shù)之間的極端匹配。例如,編程者將經(jīng)常從代碼復(fù)制多于一個的函數(shù)(他們經(jīng)常復(fù)制或修改許多函數(shù))。因此,進(jìn)行檢查或驗(yàn)證以確定是否許多函數(shù)(甚至是具有很少標(biāo)志的函數(shù))表現(xiàn)為源自于相同的文件。如果兩個文件具有相似的函數(shù),則它們很可能是相似的。在一個示例性實(shí)施例中,一個閾值約為10。例如,如果兩個文件之間有≥10個相似函數(shù),則它們很可能是由于代碼重用的原因。
根據(jù)本發(fā)明的實(shí)施例比較兩個或更多函數(shù)(或從函數(shù)得出的標(biāo)志集合)以確定函數(shù)之間的相似性。給定相同語言的兩個源代碼文件,確定是否存在相似函數(shù)。此外,本發(fā)明的實(shí)施例也能夠應(yīng)用于二進(jìn)制文件和文本文件。例如,給定兩個二進(jìn)制文件,確定對象代碼是否相似。在此,相似的操作代碼序列通常要求相似的源代碼。對于文本比較,每個段或文本塊被看作函數(shù)。每個單詞為標(biāo)志(例如,使用不區(qū)分大小寫的方法并去除非單詞字符)。
根據(jù)本發(fā)明的實(shí)施例由此創(chuàng)建基于語言(源代碼、二進(jìn)制文件、文本等)的標(biāo)志。如以下所述,示例性實(shí)施例也為許多不同的函數(shù)做了最優(yōu)化的。
根據(jù)本發(fā)明的實(shí)施例確定兩個函數(shù)是否相似或匹配并不局限于任何特定標(biāo)準(zhǔn)、閾值、數(shù)字、因素等。在一個示例性實(shí)施例中,給定矩陣A×B(例如,如結(jié)合圖3A-3E所注意的),當(dāng)(1)A*B至少約80%到90%;(2)B*A至少約80%到90%;(3)兩個集合中的至少10個符號匹配(該情形阻止了在匹配中由短集合生成錯誤-消極);和/或(4)對準(zhǔn)的序列之間的間隙不超過5個符號寬度(例如,“hello”與“hel_o”對準(zhǔn)表示一個符號的間隙),就確定是類似性匹配。
在一個示例性實(shí)施例中,為了降低來自大型循環(huán)的影響,比對矩陣算法被最優(yōu)化。遍歷所述矩陣不超過一次。最優(yōu)化算法的復(fù)雜度為O(|A|·|gB|),gB為序列B最大間隙的大小。gB的大小不大于|B|,并且通常顯著小于|B|。例如,對所述算法的最優(yōu)化包括一個或多個字節(jié)流水線傳送(byte pipelining)、子矩陣掃描、間隙截斷(gap truncation)、比較限制、比較截斷、比較忽略和串比較。此外,編程慣例最優(yōu)化包括一個或多個矩陣存儲器分配和預(yù)處理相對高速緩存(preprocessingversus caching)。
在字節(jié)流水線傳送中,矩陣被布局為大型陣列(a,b)=AxB[a]·|B|+b]。使用該布局,沿B軸的所有字節(jié)都是順序的。這種排列允許由于線性存儲器訪問的數(shù)據(jù)流水線傳送。
在子矩陣掃描中,使用矩陣中的各種傳遞(例如分配0/1值的第一傳遞,更新單元的第二傳遞,掃描子矩陣的第三傳遞)。在最優(yōu)代碼中,僅使用一個傳遞來通過整個矩陣。算法的填充屬性之一沿著外邊緣放置任意子矩陣的最大值。這樣就無需掃描任意子矩陣的內(nèi)部;而僅需要掃描外邊緣。在一個示例性實(shí)施例中,所述算法為對于每個單元(a,b)沿著外邊緣查找最大值邊緣#1[(0,b-1),(a-1,b-1)]邊緣#2[(a-1,0),(a-1,b-1)]把最大值添加到等同檢查A[a]=B[b]?把該值存儲到該單元中結(jié)果是為確定任意子矩陣的最大值而掃描的單元明顯減少。
在間隙截斷中,對準(zhǔn)符號之間的最大允許間隙可被用作限制。當(dāng)確定矩陣位置(a,b)的值時,子矩陣掃描僅檢查子矩陣的外邊緣[(a-1,0)至(a-1,b-1)]和[(0,b-1)至(a-1,b-1)]。對于a或b中相對較大的值,該掃描需要相對大量的時間。作為最優(yōu)化,掃描對應(yīng)于間隙的邊緣。例如,如果最大允許間隙為3,則所述子矩陣掃描減少至[(a-1,b-4)至(a-1,b-1)]和[(a-4,b-1)至(a-1,b-1)]。
在比較限制中,示例性實(shí)施例識別最優(yōu)匹配。如果最小匹配值相對較大,則僅僅沿矩陣的中對角線的單元與匹配有關(guān)。這樣,與匹配無關(guān)的單元無需掃描。例如,假設(shè)兩個20的序列相比較,并要求90%匹配。所述匹配僅要求最大值不小于16(即,20的90%)。
在比較截斷中,以對A序列的最小要求匹配沿B軸對矩陣進(jìn)行掃描。特別地,對于任意列“a”,驗(yàn)證或檢查最大“b”矩陣值是否足以導(dǎo)致匹配。當(dāng)不可能匹配時,跳過矩陣的剩余部分。
比較忽略與比較限制的相似之處在于,如果|A|和|B|明顯不同,則可能不會匹配。例如,如果兩個序列均必須90%匹配,但是|A|<90%·|B|,則這兩個序列不匹配。這樣,跳過整個矩陣的填充和比較。
在串比較中,符號被存儲為串。不過,strcmp()不是一個快速函數(shù)。為了減少strcmp()調(diào)用的數(shù)量,每個串以一字節(jié)的校驗(yàn)和(串中所有字節(jié)的和)作為前序。對于多數(shù)比較,所述校驗(yàn)和的值不同,表示strcmp()不匹配并且無需被調(diào)用。當(dāng)串相同或存在校驗(yàn)和沖突時,僅發(fā)生對strcmp()的調(diào)用。
在大型序列中,分配和初始化矩陣可能需要重要的處理資源。在一個示例性實(shí)施例中,最優(yōu)化矩陣存儲器。在初始化中,所述矩陣既未分配也沒有初始化,除非存在所述矩陣導(dǎo)致匹配的機(jī)會。如果序列大小不同以致于使得它們不能導(dǎo)致成功的對準(zhǔn),則所述矩陣不需要被訪問。在再分配中,當(dāng)處理每個文件多個序列時,所述矩陣不被再分配,除非其需要是更大的。例如,如果第一比較需要400個單元,第二比較需要96個單元,則矩陣存儲器在順序調(diào)用之間既不被釋放也不被再分配。所述矩陣僅當(dāng)該比較需要400個單元時才被再分配。在組織中,所述矩陣被分配為單個陣列而不是二維結(jié)構(gòu)。該實(shí)施例允許重用而無需考慮序列的大小。例如,20×20的矩陣和10×40的矩陣均能夠使用相同的分配的矩陣。
在一個示例性實(shí)施例中,過濾函數(shù)將輸入文件轉(zhuǎn)換為符號集合。從而,過濾器將所需數(shù)據(jù)轉(zhuǎn)換為符號序列。例如,操作代碼過濾器將編譯的對象的可執(zhí)行體轉(zhuǎn)換為具有已識別函數(shù)的符號序列。該過濾器在多個階段之中操作(例如獲取操作代碼,識別函數(shù)和去除常數(shù))。
在初始化階段,獲取操作代碼。例如,所述過濾器在可執(zhí)行體或?qū)ο蟠a上運(yùn)行命令“objdump-d”。參數(shù)“-d”將操作序列譯碼為匯編語言。反匯編器顯示每個函數(shù)名和函數(shù)內(nèi)的操作代碼,每行一個匯編代碼。
在第二階段期間,去除非函數(shù)和二進(jìn)制代碼。例如,每個函數(shù)名被以單詞“Function”和新行作為前序。所述新行允許算法識別下一個函數(shù)代碼的開始。在一個示例性實(shí)施例中,每個匯編行被以一周期為前序,由于一些函數(shù)包含沒有被解析為文本操作代碼的填充(例如,0的序列)。若沒有初始周期,則填充行會作為新行出現(xiàn)且不會正確地指示下一個函數(shù)的開始。
在第三階段期間,從代碼中去除約束。被反匯編的代碼包括鏈接時間約束,當(dāng)重用所述代碼,鏈接時間約束可以變化。在一個示例性實(shí)施例中,去除所有的常量值。
來自過濾器的結(jié)果是偽唯一的(pseudo-unique)匯編命令集合。對于大型序列(10個或更多匯編行),兩個不同函數(shù)具有類似部分而不具有代碼重用的可能性顯著地降低。
根據(jù)本發(fā)明的實(shí)施例并不局限于任何特定類型的過濾。如果被實(shí)現(xiàn),過濾技術(shù)部分取決于特定的軟件語言。由于大多數(shù)Linux內(nèi)核源代碼以ANSI-C書寫,所以提供了過濾C語言的示例性實(shí)施例。
作為一個觀察,當(dāng)編程者使用C源代碼時,他們通常生成以下格式化變化中的一個或多個(1)改變諸如制表符和縮進(jìn)之類的白空間;(2)增加、修改或去除注釋;(3)改變變量和附屬函數(shù)名;(4)改變諸如串或常量之類的靜態(tài)值;(5)增加附加行或去除現(xiàn)有行。
作為另一個觀察,當(dāng)編程者使用C源代碼時,他們通常不會改變以下的一個或多個(1)標(biāo)志的數(shù)目和相對位置(例如,符號、圓括號、范圍、數(shù)學(xué)運(yùn)算符)保持類似;(2)變量、串和函數(shù)的數(shù)目和相對位置保持類似(例如,代碼重用可以改變函數(shù)的名稱,但函數(shù)卻很少被改變?yōu)樽兞炕虼?;以及(3)函數(shù)參數(shù)的數(shù)目和類型保持類似。
在一個示例性實(shí)施例中,C源代碼的過濾器運(yùn)行于幾個不同階段,包括(1)去除注釋和標(biāo)記范圍;(2)識別函數(shù);(3)替換參數(shù);以及(4)去除標(biāo)記;但并不局限于此。
在第一階段期間(即,去除注釋和標(biāo)記范圍),將整個源文件加載到存儲器中。當(dāng)所述文件加載后,用以下中的一個或多個對數(shù)據(jù)進(jìn)行預(yù)處理(1)去除所有ANSI-C注釋;(2)去除所有C++注釋;(3)去除所有編譯器指示;(4)去除新行;(5)識別開始和結(jié)束引號和雙引號;(6)以當(dāng)前范圍深度標(biāo)記新范圍。該預(yù)處理的結(jié)果為包括所有活動源代碼對象的單個行。所述行包括識別匹配范圍和串的標(biāo)記。
在第二階段期間(即,識別函數(shù)),函數(shù)作為單詞空間出現(xiàn),之后跟隨一組0范圍圓括號“(0...)0”和一組0范圍大括號“{0...}0”。去除所有非函數(shù)元素。所去除的項(xiàng)包括函數(shù)原型、結(jié)構(gòu)定義、全局變量、宏、函數(shù)返回參數(shù)定義和所去除的圓括號和大括號之間的任意變量定義,但并不局限于此。該階段的結(jié)果是包含函數(shù)名和函數(shù)范圍的長串。
作為第二階段的子集,進(jìn)行標(biāo)志分離。C預(yù)分析器(preparser)允許一些標(biāo)志與變量或函數(shù)名相鄰。為了簡化過濾過程,將標(biāo)志清楚地分離開。一些示例包括分號(每個分號之前或之后添加有空間)、逗號,++和--賦值操作符被填充有白空間,所有的單詞標(biāo)志被填充有白空間。由于一些項(xiàng)目被錯誤分離,可增加第二階段來替代一些項(xiàng)目(例如,任何由數(shù)字所跟隨的范圍把空間去除掉了,并且連接了復(fù)雜的變量)。
作為第二階段的另一個子集,進(jìn)行變量替換。所有的變量和函數(shù)名由單詞“var”所替換。對于類似比較,變量的重用并不重要(僅僅是變量的頻率和位置而已)。雖然此替換不會在變量和函數(shù)之間造成差異,但是函數(shù)仍然能夠被“var”串之后的圓括號所識別。在一個示例性實(shí)施例中,僅僅沒有被替代的變量才是特定于C語言的串。
作為第二階段的另一個子集,進(jìn)行串替換。例如,替換所有用“<...>”和‘<...>’的串。雙引號用文本“string”所替代,而單引號用“char”所替代。相似地,數(shù)字(用
+或0x
+所標(biāo)示)用“num”所替換。
作為第二階段的再另一個子集,進(jìn)行變量定義去除。在一個示例性實(shí)施例中,該子集在函數(shù)內(nèi)包括四類動作(1)賦值a=b,a++;(2)運(yùn)算符a>b,a+b;(3)函數(shù)a;(4)聲明int a。在一個示例性實(shí)施例中,聲明僅僅是函數(shù)內(nèi)的幾行,這幾行不生成任何操作代碼序列。
在第三階段期間(即,替換參數(shù)),注意到參數(shù)“(0...)0”可能在函數(shù)定義內(nèi)。在代碼重用期間,參數(shù)類型(“int”或“struct complex*”)和變量名能夠變化。同時,參數(shù)的數(shù)目保持類似??梢栽黾踊蛉コ龓讉€參數(shù),但是參數(shù)的總數(shù)保持相同。在一個示例性實(shí)施例中,每個參數(shù)(原型和名稱)用單詞“parm”所替代。例外是被去除的空參數(shù)。
在第四階段期間(即,去除標(biāo)記),注意到重用的源代碼能夠包括附加范圍。為了防止范圍標(biāo)記被使用,去除所有的范圍深度標(biāo)記。例如,“{0...}0”變?yōu)椤皗...}”。
在第四階段之后,最終的結(jié)果是包含函數(shù)名和標(biāo)志的文件,每行一個標(biāo)志。此外,在過濾之后,代碼僅包含指示C標(biāo)志、變量和串的符號。再此外,每個函數(shù)的符號序列是每個代碼功能性的偽唯一。對于大型序列,兩個諸多不同的函數(shù)具有相似標(biāo)志序列的機(jī)會變得非常小。
使用根據(jù)本發(fā)明的實(shí)施例,在許可證復(fù)審過程中對人為干預(yù)的需顯著地減少了,其原因在于目標(biāo)函數(shù)與比較函數(shù)被比較以確定目標(biāo)函數(shù)是否受到一個或多個已知或預(yù)先存在的軟件許可證的約束。一旦生成輸出(例如,在報告中顯示或打印),復(fù)審者能夠輕易復(fù)審數(shù)千個文件以確定是否有什么文件包含受許可證約束的代碼。
根據(jù)本發(fā)明的實(shí)施例被用于各種系統(tǒng)、方法和設(shè)備。圖4圖示了作為計算機(jī)系統(tǒng)400的示例性實(shí)施例,其用于利用根據(jù)本發(fā)明實(shí)施例的一個或多個流程圖和/或方面。
系統(tǒng)400包括主機(jī)計算機(jī)系統(tǒng)420和知識庫、倉庫或數(shù)據(jù)庫430。所述主機(jī)計算機(jī)系統(tǒng)420包括處理單元450(例如一個或多個中央處理單元的處理器,CPU),用于控制存儲器460(例如臨時存儲數(shù)據(jù)的隨機(jī)訪問存儲器(RAM)和持久存儲數(shù)據(jù)的只讀存儲器(ROM))和算法470(可置于存儲器460或其它位置)的整體操作。所述存儲器460例如,存儲數(shù)據(jù)、控制程序和與主機(jī)計算機(jī)系統(tǒng)420相關(guān)聯(lián)的其它數(shù)據(jù)。所述處理單元450通過總線490與存儲器460、數(shù)據(jù)庫430、算法470(例如比對算法)和許多其它部件進(jìn)行通信。這些算法包括圖1和2的流程圖及其變化,但并不局限于此。
根據(jù)本發(fā)明的實(shí)施例并不局限于任何特定類型或數(shù)量的數(shù)據(jù)庫和/或主機(jī)計算機(jī)系統(tǒng)。例如,所述主機(jī)計算機(jī)系統(tǒng)包括各種便攜式和非便攜式計算機(jī)和/或電子裝置。示例性主機(jī)計算機(jī)包括計算機(jī)(便攜式和非便攜式)、服務(wù)器、大型計算機(jī)、分布式計算設(shè)備、膝上型電腦和其它電子設(shè)備和系統(tǒng)(無論這種設(shè)備和系統(tǒng)是便攜式和非便攜式的都是如此),但并不局限于此。
如在此使用的,術(shù)語“源代碼”意味著以特定編程語言書寫的程序指令。此外,如在此使用的,術(shù)語“開放源”指對于普通公眾可免費(fèi)獲取來使用或修改的程序或源代碼。此外,如在此使用的,術(shù)語“許可證”意味著授予某團(tuán)體使用知識產(chǎn)權(quán)的明確權(quán)力的契約或條款以及條件。因此,為了使用、修改或再發(fā)布開放源,開放源許可證向許可證頒發(fā)者聲明條款、條件和/或限制。開放源通常包括或受到開放源許可證的約束。例如,這樣的許可證關(guān)于如何使用、發(fā)布或修改源代碼,能夠規(guī)定不同的標(biāo)準(zhǔn)和限制。例如,一些標(biāo)準(zhǔn)包括但并不局限于以下許可的軟件不能在以許可的軟件所發(fā)布的其它軟件上執(zhí)行限制,所有人平等訪問軟件,對軟件的權(quán)力在作為特定軟件發(fā)布的部分的軟件上并不是暫時的,作者必須允許修改或派生作品并保持原始名稱,禁止程序發(fā)布的收集和特許權(quán),以及禁止試圖反對特定領(lǐng)域的說明。
在一個示例性實(shí)施例中,流程圖中的一個或多個模塊是自動的。換句話說,設(shè)備、系統(tǒng)和方法自動發(fā)生。如在此使用的,術(shù)語“自動的”或“自動地”(以及其變化)意味著使用計算機(jī)和/或機(jī)械/電子裝置控制設(shè)備、系統(tǒng)和/或過程,而無需人為干預(yù)、觀察、花費(fèi)精力和/或決策。
提供根據(jù)本發(fā)明實(shí)施例的流程圖作為示例,而不應(yīng)被認(rèn)為是對本發(fā)明范圍內(nèi)其它實(shí)施例的限制。例如,各模塊不應(yīng)被解釋為是必須以特定順序執(zhí)行的步驟。可以增加附加模塊/步驟,去除一些模塊/步驟,或改變模塊/步驟的順序,仍然屬于本發(fā)明的范圍。此外,不同附圖中的模塊可以加入其它附圖,或者與其它附圖的模塊交換。再此外,應(yīng)當(dāng)理解的是,特定數(shù)字?jǐn)?shù)據(jù)值(例如特定數(shù)量、數(shù)字、種類等)或其它特定信息是說明性的,用于討論示例性實(shí)施例。這種特定的信息并不是提供來限制本發(fā)明的。
在根據(jù)本發(fā)明的各個實(shí)施例中,實(shí)施例被實(shí)現(xiàn)為方法、系統(tǒng)和/或設(shè)備。如一個示例,示例性實(shí)施例被實(shí)現(xiàn)為執(zhí)行在此所描述的方法的一個或多個計算機(jī)軟件程序。所述軟件被實(shí)現(xiàn)為一個或多個模塊(也看作代碼子例程,或面向?qū)ο缶幊讨械摹皩ο蟆?。所述軟件的位置對于各種不同的實(shí)施例能夠是不同的。例如,所述軟件編程代碼由計算機(jī)或服務(wù)器的處理器或多個處理器從一些類型的長期存儲介質(zhì)中訪問,所述長期存儲介質(zhì)例如CD-ROM驅(qū)動器或硬盤。所述軟件編程代碼收錄或存儲于任意已知的介質(zhì),用于與數(shù)據(jù)處理系統(tǒng)或在任何存儲器裝置中來使用,所述存儲器裝置例如半導(dǎo)體、磁和光裝置,包括磁盤、硬盤、CD-ROM、ROM等。所述代碼分布于這樣的介質(zhì)上或發(fā)布給用戶,從計算機(jī)系統(tǒng)的存儲器或存儲中通過一些類型的網(wǎng)絡(luò)發(fā)布到其它計算機(jī)系統(tǒng),由這些其它系統(tǒng)的用戶使用。作為選擇,編程代碼收錄于存儲器(例如手持便攜式電子裝置的存儲器)中并由處理器通過總線訪問。將軟件編程代碼收錄在存儲器中、物理介質(zhì)上和/或通過網(wǎng)絡(luò)發(fā)布軟件代碼的技術(shù)和方法是公知的,在此不再進(jìn)一步討論。
以上討論試圖說明本發(fā)明的原理和各個實(shí)施例。一旦充分理解以上公開,多種變化和修改對于本領(lǐng)域技術(shù)人員就會變得顯而易見。以下權(quán)利要求試圖包括所有這樣的變化和修改。
權(quán)利要求
1.一種軟件執(zhí)行方法,包括把軟件代碼劃分為多個函數(shù)(120);把每個函數(shù)變換為多個標(biāo)志(140);把所述多個標(biāo)志與對應(yīng)于已知函數(shù)的一組標(biāo)志相比較(150),所述已知函數(shù)受軟件許可證的約束。
2.如權(quán)利要求1所述的方法,進(jìn)一步包括確定所述軟件代碼是否包括所述已知函數(shù)的修改版本并由此受所述軟件許可證的約束(160)。
3.如權(quán)利要求1所述的方法,進(jìn)一步包括基于對所述多個標(biāo)志和所述一組標(biāo)志是共同的若干標(biāo)志來確定所述多個函數(shù)和所述已知函數(shù)之間的相似性(160)。
4.如權(quán)利要求1所述的方法,進(jìn)一步包括為了確定所述多個函數(shù)中的至少一個和所述已知函數(shù)之間的相似性,在矩陣中排列所述多個標(biāo)志中的至少一個和所述一組標(biāo)志9220)。
5.如權(quán)利要求1所述的方法,進(jìn)一步包括用第一普通術(shù)語替換所述多個標(biāo)志中的變量,并且用第二普通術(shù)語替換所述多個標(biāo)志中的數(shù)字(130)。
6.一種計算機(jī)系統(tǒng)(420),包括存儲器(460),用于存儲算法(470);和處理器(450),用于執(zhí)行所述算法,用來從(1)受軟件許可證約束的第一函數(shù)和(2)第二函數(shù)構(gòu)造矩陣(220);計算所述矩陣中的對準(zhǔn)路徑以確定所述第二函數(shù)是否是所述第一函數(shù)的修改(240)。
7.如權(quán)利要求16所述的計算機(jī)系統(tǒng),其中所述處理器進(jìn)一步執(zhí)行所述算法,用來在一遍遍歷通過矩陣中確定沿所述矩陣的外邊緣的任意子矩陣的最大值。
8.如權(quán)利要求16所述的計算機(jī)系統(tǒng),其中所述處理器進(jìn)一步執(zhí)行所述算法,用來從所述第二函數(shù)去除注釋和標(biāo)記范圍。
9.如權(quán)利要求16所述的計算機(jī)系統(tǒng),其中所述處理器進(jìn)一步執(zhí)行所述算法,用來從所述第二函數(shù)去除非函數(shù)元素,以生成包含函數(shù)名和函數(shù)范圍的串。
10.如權(quán)利要求16所述的計算機(jī)系統(tǒng),其中所述處理器進(jìn)一步執(zhí)行所述算法,用來替換所述第二函數(shù)中的變量、函數(shù)名和串(130)。
全文摘要
實(shí)施例包括用于發(fā)現(xiàn)軟件文件是否與許可證相關(guān)聯(lián)的方法、設(shè)備和系統(tǒng)。軟件執(zhí)行的一個方法包括把軟件劃分為多個函數(shù)(120),把每個函數(shù)變換為多個標(biāo)志(140),以及把所述多個標(biāo)志與對應(yīng)于已知函數(shù)的一組標(biāo)志相比較(150),所述已知函數(shù)受軟件許可證的約束。
文檔編號G06F21/22GK101093533SQ20071011216
公開日2007年12月26日 申請日期2007年6月19日 優(yōu)先權(quán)日2006年6月19日
發(fā)明者N·克拉維茨 申請人:惠普開發(fā)有限公司