程靖云,王布宏,羅鵬
(空軍工程大學(xué) 信息與導(dǎo)航學(xué)院,西安 710077)
隨著信息技術(shù)的快速發(fā)展,各行各業(yè)對計算機軟件的需求不斷增加,軟件中存在的大量安全缺陷給計算機系統(tǒng)留下了巨大的安全隱患,黑客可以利用某些安全缺陷入侵目標(biāo)[1]。由于軟件規(guī)模和復(fù)雜度的增加,僅依靠人工檢測或常規(guī)的檢測工具難以保證代碼缺陷檢測的效率和準(zhǔn)確性。因此,實現(xiàn)代碼缺陷的快速和準(zhǔn)確定位已經(jīng)成為安全領(lǐng)域的一個關(guān)鍵問題[2]。
代碼缺陷檢測技術(shù)可以分為靜態(tài)、動態(tài)和混合分析方法。靜態(tài)分析不執(zhí)行軟件或程序,基于源代碼的屬性特征檢測缺陷,具有更高的執(zhí)行效率和代碼覆蓋率,但誤報率較高;動態(tài)分析利用特定輸入執(zhí)行程序,基于軟件或程序的行為特征檢測缺陷,具有更高的檢測精度,但在分析大量代碼時執(zhí)行效率和覆蓋率低,且漏報率高;混合分析同時應(yīng)用靜態(tài)和動態(tài)分析,但也繼承了兩者的局限性[3]。據(jù)通用漏洞披露(Common Vulnerabilities &Exposures,CVE)報告,截至2021年7月,CVE 中記錄的漏洞數(shù)量已經(jīng)超過15 萬個[4]。面對已經(jīng)披露的大量安全缺陷和未知的零日漏洞,綜合考慮執(zhí)行效率、代碼覆蓋率和檢測效果等因素,靜態(tài)分析技術(shù)在效率和有效性之間取得了較好的平衡,并能夠在早期發(fā)現(xiàn)安全缺陷,被廣泛應(yīng)用于代碼分析和缺陷檢測。但傳統(tǒng)的靜態(tài)分析方法,比如Flawfinder、RATS(Rough Auditing Tool for Security)和Checkmarx 等靜態(tài)分析工具基于特定規(guī)則檢測缺陷,難以發(fā)現(xiàn)預(yù)定義規(guī)則之外的代碼缺陷[5];基于代碼相似性的方法根據(jù)代碼的重用特性,能夠檢測涉及精確、重命名、重組和語義克隆的代碼缺陷,但依賴于缺陷代碼模板的數(shù)量和質(zhì)量,并且對非克隆代碼檢測效果較差[6-7]。這些靜態(tài)分析方法依賴于安全專家的經(jīng)驗以及前期繁重的特征工程等技術(shù),其泛化能力較差。
為了提高代碼缺陷檢測的性能,機器學(xué)習(xí)[8]和數(shù)據(jù)挖掘技術(shù)[9]已經(jīng)被用于代碼的靜態(tài)分析,人工智能的發(fā)展使得代碼缺陷檢測和零日漏洞挖掘更加智能化[10]?;谏疃葘W(xué)習(xí)的方法能夠挖掘源代碼間的關(guān)系,自動學(xué)習(xí)脆弱代碼的模式,通過匹配源代碼的潛在特征來實現(xiàn)快速、準(zhǔn)確的代碼缺陷檢測和定位,但以往的研究主要關(guān)注程序、包、組件和文件級別的粗粒度特征,難以精確定位缺陷代碼的位置[2]。Russell等[11]提出將源代碼進(jìn)行標(biāo)記的方法,利用卷積神經(jīng)網(wǎng)絡(luò)(Convolutional Neural Network,CNN)檢測函數(shù)級別的代碼缺陷,但同時引入了大量與缺陷無關(guān)的代碼。Zhou等[12]提出了基于圖神經(jīng)網(wǎng)絡(luò)(Graph Neural Network,GNN)的代碼缺陷檢測系統(tǒng)Devign,利用源代碼的復(fù)合圖表示來識別缺陷代碼的模式,但只能在方法級別定位代碼缺陷,并且計算復(fù)雜度較高。許健等[13]提出利用抽象語法樹(Abstract Syntax Tree,AST)表示源代碼的結(jié)構(gòu)和語義信息,并通過滑動哈希窗口進(jìn)一步減小了方法體的特征維度,但只對整數(shù)溢出類型進(jìn)行了檢測。Li等[14]提出根據(jù)應(yīng)用程序編程接口(Application Programming Interface,API)調(diào)用和數(shù)據(jù)流信息進(jìn)行程序切片,只提取源代碼中與缺陷相關(guān)的語句,將檢測粒度精細(xì)到切片級別,并通過雙向長短期記憶(Bi-directional Long Short-Term Memory,BiLSTM)網(wǎng)絡(luò)來檢測代碼缺陷,但涉及的缺陷類別只包括緩沖區(qū)錯誤和資源管理錯誤。李元誠等[15]提出了一種混合深度學(xué)習(xí)方法,利用深度卷積神經(jīng)網(wǎng)絡(luò)快速處理特征數(shù)據(jù),并通過門控循環(huán)單元(Gated Recurrent Unit,GRU)保留代碼間的調(diào)用關(guān)系,在檢測切片級別缺陷時取得了較好的效果,但涉及的代碼樣本和覆蓋的缺陷類型較少。王曉萌等[16]對代碼進(jìn)行反向數(shù)據(jù)流分析生成后向切片,并融合兩種詞向量來表示代碼令牌,但沒有考慮控制流信息。Li等[17]在文獻(xiàn)[14]的基礎(chǔ)上引入了控制流信息,提出了一種基于最小中間表示學(xué)習(xí)(Minimum Intermediate Representation Learning,MIRL)的代碼缺陷檢測方法,根據(jù)系統(tǒng)依賴圖(System Dependence Graph,SDG)獲取源代碼的安全切片,構(gòu)建了連接式CNN 模型提取代碼特征,并利用支持向量機(Support Vector Machine,SVM)對特征進(jìn)行二次訓(xùn)練,但時間復(fù)雜度較高。Jeon等[18]提出了AutoVAS脆弱性分析系統(tǒng),通過提取易損API 和系統(tǒng)調(diào)用處的切片進(jìn)行代碼缺陷檢測,并綜合分析了不同因素對檢測性能的影響,但可能漏報易損API 之外的關(guān)鍵點。
針對上述問題,在數(shù)據(jù)層面,可以采用合適的切片方法,在提取更細(xì)粒度代碼片段的同時保留足夠的信息;在模型層面,可以采用增強或組合的機制最大限度地學(xué)習(xí)代碼中的特征。同時,由于源碼中存在代碼復(fù)用現(xiàn)象,需要對不同缺陷類型進(jìn)行測試,以評估模型的泛化能力。因此,本文采用基于過程間有限分布子集(Interprocedural Finite Distributive Subset,IFDS)的切片方法,在源代碼關(guān)鍵點上獲取包含數(shù)據(jù)流和控制流信息的雙向程序切片;同時,通過文本卷積神經(jīng)神經(jīng)網(wǎng)絡(luò)(Text CNN,TextCNN)的多通道機制提取代碼切片中的局部關(guān)鍵特征,采用雙向門控循環(huán)單元(Bi-directional GRU,BiGRU)捕捉切片序列中的上下文序列特征,融合兩部分特征作為代碼片段的特征表示,用于代碼缺陷檢測。最后,對比分析了不同的缺陷類型、切片方法、關(guān)鍵點選取和模型等因素對檢測性能的影響,并與類似工作進(jìn)行了對比實驗,驗證了本文方法在代碼缺陷檢測上的有效性。
本文提出了基于程序切片和語義特征融合的代碼缺陷靜態(tài)檢測方法,將程序切片技術(shù)和語義分析用于程序源代碼的處理和分析,本文方法的總體框架如圖1 所示。
本文方法主要包含以下幾個階段:
1)數(shù)據(jù)預(yù)處理。對源代碼中的關(guān)鍵點進(jìn)行數(shù)據(jù)流和控制流分析,通過程序切片獲取代碼片段,規(guī)范化代碼片段中的變量名和函數(shù)名。
2)預(yù)訓(xùn)練階段。將代碼片段令牌化,獲得最小中間表示(Minimum Intermediate Representation,MIR)[17],用代碼令牌(Token)構(gòu)建代碼片段數(shù)據(jù)集的語料庫,通過詞向量法訓(xùn)練生成嵌入矩陣。
3)模型構(gòu)建。將嵌入矩陣作為模型的嵌入層,通過填充或截斷的方式將令牌序列轉(zhuǎn)換為固定長度后輸入嵌入層,用構(gòu)建的網(wǎng)絡(luò)提取特征來訓(xùn)練代碼缺陷檢測模型。
從源代碼的角度來看,大多數(shù)代碼缺陷都源于一個引發(fā)安全問題的關(guān)鍵點,例如函數(shù)、賦值或控制語句。代碼缺陷的產(chǎn)生往往是由多條具有邏輯關(guān)系的代碼語句導(dǎo)致的,在一定條件下,安全缺陷會在某一關(guān)鍵點處被觸發(fā)。程序源代碼中存在大量的代碼語句,其中只有部分語句與代碼缺陷的產(chǎn)生聯(lián)系。為了降低無關(guān)語句的影響,在更細(xì)粒度上檢測代碼缺陷,本文利用數(shù)據(jù)流和控制流分析技術(shù),對代碼缺陷產(chǎn)生的關(guān)鍵點進(jìn)行程序切片,獲得由多行與代碼缺陷相關(guān)的代碼語句組成的代碼片段。
程序切片技術(shù)分為前向切片和后向切片,根據(jù)代碼中關(guān)鍵點函數(shù)或變量的特性,需要采用不同的切片技術(shù)[19]。本文采用底層虛擬機(Low Level Virtual Machine,LLVM)對C源代碼進(jìn)行分析,獲取程序的前向或后向切片,通過采用基于IFDS 的切片方法,在充分考慮源代碼中的數(shù)據(jù)依賴和控制依賴信息的同時,構(gòu)建函數(shù)內(nèi)或函數(shù)間的代碼切片。
以圖2 所示的源代碼為例,代碼第9 行snprintf API 函數(shù)處會發(fā)生緩沖區(qū)溢出。第8 行的malloc 函數(shù)為變量buf 分配了一個64 字節(jié)的內(nèi)存,當(dāng)變量str 的大小超過64 字節(jié)時,將會導(dǎo)致緩沖區(qū)溢出,因此這里選?。?,snprintf(buf,128,"<%s>",str);/*string copy*/>作為關(guān)鍵點。用數(shù)字代表對應(yīng)行號的代碼語句,則該關(guān)鍵點數(shù)據(jù)依賴于{16,19,20,7,8},控制依賴于{14,17,6},通過反向程序切片獲取該缺陷的范圍為{14,16,17,19,20,6,7,8,9}。從該示例可以看出,雖然緩沖區(qū)溢出只發(fā)生在snprintf 函數(shù)處,但該缺陷的發(fā)生與源代碼上下文語義存在長依賴關(guān)系,多條代碼語句按一定的執(zhí)行邏輯將會導(dǎo)致這一缺陷。因此,在進(jìn)行代碼缺陷檢測時,不僅要關(guān)注缺陷可能發(fā)生的關(guān)鍵點,還要分析可能會導(dǎo)致這一缺陷的上下文信息。通常在易損API 處更易產(chǎn)生缺陷,但兩者之間并無絕對聯(lián)系,代碼中某些不當(dāng)使用的變量被傳遞到能夠?qū)е鲁绦虍惓;虮罎⒌狞c時,缺陷才會體現(xiàn)出來。針對圖2 所示的源代碼,若以變量為關(guān)鍵點,采用IFDS切片方法可以獲得如表1 所示的靜態(tài)切片表,其中包含了變量及相關(guān)的后向或前向切片代碼行。
表1 靜態(tài)切片表Tab.1 Static slice table
源代碼中存在大量與代碼缺陷無關(guān)的語句和單詞,比如注釋、用戶自定義的函數(shù)和變量等,它們不會影響程序的執(zhí)行邏輯和語義,但大量的無關(guān)語句和字符串會造成信息冗余,影響代碼缺陷檢測的效率和準(zhǔn)確性。因此,在進(jìn)行程序切片后,將用戶自定義的函數(shù)和變量進(jìn)行統(tǒng)一替換,函數(shù)名用FUNC#表示,變量名用VAR#表示,其中#表示函數(shù)或變量在代碼片段中出現(xiàn)的序號。最后,利用通配符匹配并規(guī)范化代碼片段中包含“CWE”“good”“bad”等關(guān)鍵字的令牌。通過統(tǒng)一的符號表示,將代碼片段進(jìn)一步規(guī)范化,能夠減少人為因素對代碼缺陷檢測效果的影響,同時可以壓縮嵌入層中詞匯表的大小,降低運算復(fù)雜度。
對經(jīng)過數(shù)據(jù)預(yù)處理的代碼片段作分詞處理,如圖2 所示,可以獲得每個數(shù)據(jù)樣本的MIR:{“int”,“main”,“(”,…,“VAR3”,“)”,“;”},從而將代碼片段轉(zhuǎn)換為類似自然語言的形式。對于一個長度為n的代碼片段T1:n,將其用MIR 表示如下:
其中:Ti為代碼中的單個Token;⊕為連接符,在代碼片段中用空格表示。
深度學(xué)習(xí)模型無法直接處理代碼片段,因此需要將代碼片段轉(zhuǎn)換為向量表示,常用的方法有one-hot 編碼、詞嵌入等方法,但one-hot 使用0、1 編碼代碼片段中的令牌,生成的是高維稀疏向量,并且沒有考慮上下文的語義關(guān)系,因此本文采用Word2vec 中的Skip-gram 模型構(gòu)建嵌入矩陣[20],模型結(jié)構(gòu)如圖3 所示。
Skip-gram 的基本思想是通過中心詞來預(yù)測上下文,進(jìn)而生成代碼Token 間具有語義關(guān)聯(lián)性的向量表示,該模型的優(yōu)化目標(biāo)函數(shù)是最大化中心詞Ti的上下文單詞Ti+j的對數(shù)概率之和:
其中:q是中心詞上下文窗口的大??;n為代碼片段的長度。
在嵌入矩陣中存儲了每個Token的d維向量表示,MIR經(jīng)過嵌入矩陣處理后,其向量表示為:
考慮到代碼缺陷的觸發(fā)與代碼中某些關(guān)鍵區(qū)域的語句緊密相關(guān),同時代碼缺陷關(guān)鍵點與上下文代碼存在較長的數(shù)據(jù)依賴和控制依賴關(guān)系,本文融合了TextCNN 和BiGRU 兩種模型的優(yōu)勢,構(gòu)建了聯(lián)合檢測模型,同時提取代碼片段中的局部關(guān)鍵特征和上下文序列特征,將兩部分特征融合進(jìn)行代碼缺陷檢測。TextCNN 通過一維卷積提取句子中類似于ngram 的局部特征,利用不同尺寸的卷積核能更好地捕捉代碼片段中的局部相關(guān)性,然后通過一維最大池化,能夠從特征圖中提取信息最豐富的局部特征[21]。BiGRU 可以更好地捕捉雙向語義依賴,建模上下文序列信息,在源代碼中可以提取關(guān)鍵點上下文中存在的數(shù)據(jù)流和控制流信息,保留代碼片段中變量和控制語句等對關(guān)鍵點的長依賴關(guān)系,同時GRU通過門控機制緩解了循環(huán)神經(jīng)網(wǎng)絡(luò)(Recurrent Neural Network,RNN)中存在的梯度消失和爆炸問題,能夠更好地處理較長的代碼片段。
構(gòu)建的缺陷檢測模型的網(wǎng)絡(luò)結(jié)構(gòu)如圖4 所示,采取詞嵌入預(yù)訓(xùn)練形成的嵌入矩陣作為模型的嵌入層,將固定長度的代碼片段輸入嵌入層即可獲得對應(yīng)的向量表示。在隱藏層分別使用TextCNN 模型和BiGRU 模型提取代碼片段的局部關(guān)鍵特征和上下文序列特征,將兩部分特征拼接后形成代碼片段的融合特征。
模型的輸入是T1∶L,將T1∶L輸入嵌入層,得到代碼片段的向量表示,如式(4)所示:
其中:Embedding表示嵌入層;L為輸入模型的代碼片段的統(tǒng)一長度;d為向量維度。
在TextCNN 結(jié)構(gòu)中,對于一個d維代碼片段,使用窗長為m的卷積核Conv1D∈Rm×d獲取詞窗口的特征ci(1 ≤i≤L-m+1),對所有窗口進(jìn)行卷積操作后可以獲得特征圖c1∶L-m+1,再通過一維最大池化,獲取信息最豐富的局部特征cmax,如式(5)~(6)所示:
其中:w為權(quán)重系數(shù);bc∈Rm為偏置向量;f為非線性激活函數(shù)ReLU(Rectified Linear Unit)。
在卷積層中,使用K種不同窗口的卷積核,以便從代碼片段中提取不同長度的局部特征,并使用N個濾波器從相同的窗口中學(xué)習(xí)互補特征,對每種窗口卷積后的結(jié)果使用一維最大池化,將不同窗口池化后的結(jié)果進(jìn)行拼接,得到K×N個特征向量cTextCNN∈RK×N:
在GRU 網(wǎng)絡(luò)結(jié)構(gòu)中,設(shè)在時間步t處的輸入為vt,t-1處的隱藏狀態(tài)為ht-1,W、U為權(quán)重系數(shù),b為偏置向量,則重置門控狀態(tài)rt和更新門控狀態(tài)zt為:
然后,將TextCNN 提取的局部特征向量cTextCNN和BiGRU提取的上下文特征向量cBiGRU拼接作為代碼片段的特征輸入全連接層;為避免過擬合,并提高模型的泛化能力,在全連接層后增加Dropout層,Dropout 比例為0.5;最后,使用Softmax函數(shù),用來預(yù)測類別概率。
本文實驗采用Tensorflow 2.4.1 深度學(xué)習(xí)框架,開發(fā)語言為Python 3.8.10。所用的計算機環(huán)境為Windows10 操作系統(tǒng),處理器為AMD R7-5800H,內(nèi)存16 GB,硬盤512 GB,GPU GeForce RTX 3060,以及Ubuntu 18.04 虛擬機。
實驗數(shù)據(jù)集來自于美國國家標(biāo)準(zhǔn)與技術(shù)研究院(National Institute of Standards and Technology,NIST)的軟件保證參考數(shù)據(jù) 集(Software Assurance Reference Dataset,SARD)[22],本文中涉及到的缺陷類型包含CWE134(使用外部控制的格式字符串)、CWE121(堆棧緩沖區(qū)溢出)、CWE78(操作系統(tǒng)命令注入)等74 種代碼缺陷的切片。如圖5 所示,根據(jù)缺陷類型將實驗數(shù)據(jù)分為6 大類,采用分層采樣將數(shù)據(jù)集按照6∶2∶2 劃分為訓(xùn)練集、驗證集和測試集。
混淆矩陣是代碼缺陷檢測的通用評估指標(biāo),該矩陣描述了實際類別與分類模型預(yù)測類別之間的混合數(shù)目。如表2所示,真陽性TP(True Positive)表示實際為脆弱樣本被預(yù)測為脆弱樣本的數(shù)量,真陰性TN(True Negative)表示實際為非脆弱樣本被預(yù)測為非脆弱樣本的數(shù)量,假陽性FP(False Positive)表示實際為非脆弱樣本被預(yù)測為脆弱樣本的數(shù)量,假陰性FN(False Negative)表示實際為脆弱樣本被預(yù)測為非脆弱樣本的數(shù)量。
表2 混淆矩陣Tab.2 Confusion matrix
本文采用準(zhǔn)確率(Acc)、召回率(Rec)、精確度(Pre)和F1值作為評估指標(biāo)。計算公式如下:
其中:Acc表示分類正確的樣本數(shù)與樣本總數(shù)之比;Rec表示被正確預(yù)測的脆弱樣本數(shù)與脆弱樣本總數(shù)之比;Pre表示被正確預(yù)測的脆弱樣本數(shù)與預(yù)測為脆弱樣本的總數(shù)之比;F1值表示召回率和精確度的調(diào)和平均。
在構(gòu)建代碼片段的向量表示時,要綜合考慮代碼長度對檢測性能和時間復(fù)雜度的影響:如果代碼片段長度過短則會丟失部分語義信息,造成檢測的準(zhǔn)確率下降;過長則會導(dǎo)致運算復(fù)雜度增加,甚至導(dǎo)致網(wǎng)絡(luò)更新慢、梯度消失等問題。為了選擇合適的代碼片段長度,本文對比了不同代碼片段長度對準(zhǔn)確率和平均訓(xùn)練時間的影響,在保證準(zhǔn)確率的前提下,選擇了合適的代碼片段長度,減小模型在訓(xùn)練和檢測階段的時間復(fù)雜度。
如圖6 所示,隨著代碼片段長度的增加,在驗證集上的準(zhǔn)確度最終保持在91.80%左右,但是訓(xùn)練時間快速增加,因此在代碼片段末尾進(jìn)行補零或者截斷,設(shè)置統(tǒng)一長度L=50。通過控制變量法對比不同參數(shù)下模型的準(zhǔn)確率和時間復(fù)雜度,在預(yù)訓(xùn)練階段本文采用的向量表示維度為d=50,滑動窗口大小為5,迭代次數(shù)為10。本文中涉及到的主要參數(shù)如表3 所示。
表3 實驗參數(shù)Tab.3 Experimental parameters
2.5.1 不同類型缺陷檢測
為了驗證本文方法對不同類型缺陷的檢測能力,在緩沖區(qū)溢出、格式化字符串、內(nèi)存管理、錯誤處理不當(dāng)、命令執(zhí)行五大類缺陷以及小類別缺陷混合的數(shù)據(jù)集上分別進(jìn)行了實驗。
圖7 是在驗證集上檢測不同類型缺陷時本文方法的準(zhǔn)確率變化曲線。實驗結(jié)果表明,本文方法在檢測命令執(zhí)行缺陷時的收斂性較好,與緩沖區(qū)溢出、格式化字符串、內(nèi)存管理三大類缺陷在迭代2 次后就基本收斂,而在檢測錯誤處理不當(dāng)以及混合類型缺陷時收斂性較差,因為這兩類缺陷數(shù)據(jù)量小,缺陷種類較多,需要迭代多次才能達(dá)到較好的檢測效果。
表4 是在測試集上針對不同類型缺陷的檢測效果。實驗結(jié)果表明,本文方法對緩沖區(qū)溢出的檢測效果較差,各項指標(biāo)均在90%以下,這可能是因為緩沖區(qū)溢出具有更加復(fù)雜的缺陷模式,比如復(fù)雜的控制依賴和數(shù)據(jù)依賴;對其他類型缺陷檢測的準(zhǔn)確率均在90%以上,召回率均在91%以上;對命令執(zhí)行以及混合類型缺陷檢測效果較好,各項指標(biāo)均在93%以上,說明這兩型缺陷中的脆弱模式相對簡單,更容易被識別,檢測效果相對較好。綜合來看,本文方法能夠有效檢測代碼片段中存在的不同類型缺陷,適應(yīng)性較好。
表4 不同缺陷時本文方法的實驗結(jié)果對比 單位:%Tab.4 Experimental results comparison of the proposed method for different defects unit:%
2.5.2 不同切片方法
現(xiàn)有研究中,程序切片標(biāo)準(zhǔn)和方法的不統(tǒng)一導(dǎo)致生成的代碼片段存在一定差異。為了分析程序切片方法對檢測性能的影響,在包含所有類型代碼缺陷的數(shù)據(jù)集上進(jìn)行了5 次實驗,結(jié)果取平均值。
如表5 所示,本文對比了3 種切片方法:IFDS、SDG 和Weiser,獲得7 種不同類型的代碼切片。其中:Bo 表示雙向切片;Bw 表示后向切片;Fw 表示前向切片。實驗結(jié)果表明:
表5 不同切片方法的實驗結(jié)果對比Tab.5 Experimental results comparison of different slicing methods
1)同一切片方法的時間復(fù)雜度與Token 數(shù)正相關(guān)。Token 數(shù)在一定程度上反映了代碼語句的復(fù)雜度,后向切片的Token 數(shù)最少,耗時最短;雙向切片的Token 包含后向和前向切片中存在的Token,數(shù)量最多,耗時最長。
2)基于IFDS 的切片方法在雙向、后向切片上優(yōu)于基于SDG 和Weiser 的切片方法。對比3 種反向切片,Weiser 切片方法只對代碼關(guān)鍵點進(jìn)行了反向數(shù)據(jù)流分析,生成的反向切片沒有包含控制流信息,因此檢測效果最差。
3)雙向切片的綜合檢測性能(F1值)優(yōu)于反向和前向切片。結(jié)合Token 數(shù)來看,在反向切片中包含更多的Token,但檢測效果最差。通過對比分析生成的代碼片段,發(fā)現(xiàn)前向切片中包含更多與輸出相關(guān)的語句,這些語句包含的Token 對缺陷的指示信息較少,且大多與數(shù)據(jù)流相關(guān),只包含較少的控制流信息,因此檢測效果較差。
4)在規(guī)范化的切片中普遍存在代碼復(fù)用現(xiàn)象,在IFDS_Bo 類型中代碼復(fù)用比最小,能夠生成更多獨特的切片,并且相較于其他類型切片F(xiàn)1值有不同程度提升。
2.5.3 不同檢測方法
為了進(jìn)一步驗證本文方法的有效性,選擇了基于專家定義規(guī)則的靜態(tài)檢測工具:Flawfinder[23],以及基于深度學(xué)習(xí)的代碼缺陷檢測方法[15,17-18],取5 次實驗結(jié)果的平均值進(jìn)行對比。實驗中統(tǒng)一采用IFDS_Bo 的切片類型,并保持其余實驗條件相同。結(jié)果如表6 所示。
表6 不同方法的實驗結(jié)果對比Tab.6 Experimental results comparison of different methods
實驗結(jié)果表明:
1)在檢測性能上?;谏疃葘W(xué)習(xí)的方法[15,17-18]相較于靜態(tài)分析工具Flawfinder[23]在代碼缺陷檢測性能上有顯著的提升;本文模型在關(guān)鍵點為API 時的F1值比TextCNN+SVM[17]低0.21 個百分點,比DCnnGRU[15]、BiGRU[18]分別高3.80、1.16 個百分點,準(zhǔn)確率比TextCNN+SVM[17]低0.19 個百分點,比DCnnGRU[15]、BiGRU[18]分別高3.77、1.06 個百分點;在關(guān)鍵點為變量時,F(xiàn)1值比DCnnGRU[15]、TextCNN+SVM[17]、BiGRU[18]分別高2.06、0.39、0.95 個百分點,準(zhǔn)確率比TextCNN+SVM[17]低0.19 個百分點,比DCnnGRU[15]、BiGRU[18]分別高2.67、0.82 個百分點。
2)在時間復(fù)雜度上。TextCNN+SVM[17]在TextCNN 提取的特征基礎(chǔ)上,引入了SVM 對特征進(jìn)行二次訓(xùn)練,因此訓(xùn)練和檢測時間明顯增加,其他方法在一個數(shù)量級上,沒有顯著差異;關(guān)鍵點為API 比變量的時間復(fù)雜度相對較小,這可能與Token 數(shù)有關(guān)系,更多的Token 會增加嵌入層的維度。
3)在模型結(jié)構(gòu)上。DCnnGRU[15]使用了圖像處理中的多層卷積結(jié)構(gòu),破壞了一維代碼向量的整體性,同時卷積操作會丟失特征的位置信息;TextCNN+SVM[17]將特征提取模塊和分類模塊分離,一定程度上提高了模型的泛化能力,但導(dǎo)致時間復(fù)雜度顯著增加;BiGRU[18]使用自然語言處理中常用的BiGRU 模型,取得了較為均衡的檢測效果;本文模型在充分提取局部和全局特征的同時,沒有顯著增加時間復(fù)雜度,并且取得了更好的檢測效果。
綜合來看,本文方法在不顯著增加時間復(fù)雜度的同時,取得了更高的準(zhǔn)確率和F1值,通過合理的模型設(shè)計,能更有效地提取缺陷代碼的特征。
本文提出了一種基于程序切片和語義特征融合的代碼缺陷靜態(tài)檢測方法。首先,為了檢測更細(xì)粒度的代碼缺陷,采用IFDS 切片方法,在關(guān)鍵點處獲取包含數(shù)據(jù)流和控制流信息的程序切片,在保留足夠語義特征的前提下,將缺陷范圍縮小到關(guān)鍵代碼行,提高了檢測效率和定位精度;其次,針對代碼缺陷與關(guān)鍵點的強相關(guān)性以及與上下文存在的長依賴性,利用構(gòu)建的聯(lián)合檢測模型提取代碼片段的深層特征,將局部關(guān)鍵特征和上下文序列特征作為代碼片段的特征表示。實驗結(jié)果表明,本文方法能夠有效檢測不同類型的代碼缺陷,泛化能力較好;對比不同的切片類型,在IFDS 方法提取的雙向切片上綜合檢測性能最優(yōu);對比不同的關(guān)鍵點,本文方法在保證檢測效率的同時,相較于其他方法有明顯提升。深度學(xué)習(xí)是以數(shù)據(jù)為驅(qū)動,數(shù)據(jù)決定模型的上限。因此,在下一步工作中,將深入研究源代碼更合適的表示形式,比如引入有向圖結(jié)構(gòu)來表示切片中的信息流向和語句特征,在保證細(xì)粒度的同時,提高缺陷檢測的效果。同時,可以通過編譯獲取代碼的不同表示形式,采用多模態(tài)學(xué)習(xí)從不同維度捕獲更豐富的代碼特征。