江建慧, 吳捷程, 孫 亞
(同濟(jì)大學(xué) 軟件學(xué)院, 上海 201804)
錯(cuò)誤程序行為(erroneous program behavior, EPB) 分析主要是獲取程序差錯(cuò)及其對(duì)程序行為的影響,包括差錯(cuò)類型、差錯(cuò)發(fā)生位置、差錯(cuò)發(fā)生時(shí)機(jī),以及各個(gè)差錯(cuò)在程序中的表象.
軟件故障注入技術(shù)通過人為地對(duì)軟件或計(jì)算機(jī)等目標(biāo)系統(tǒng)注入軟件故障來加速其失效,從而實(shí)現(xiàn)目標(biāo)系統(tǒng)的容錯(cuò)機(jī)制有效性驗(yàn)證、可靠性評(píng)估[1-2].然而,如何得到真實(shí)的軟件故障或差錯(cuò)數(shù)據(jù)是該技術(shù)實(shí)現(xiàn)的前提[1-4].
具有代表性的軟件差錯(cuò)數(shù)據(jù)獲取需要分析軟件的功能特性及其在某個(gè)故障/缺陷被激活后所表現(xiàn)出的錯(cuò)誤行為[2-3,5],工作量很大,且分析周期很長[1,3].常見的正交缺陷分類(orthogonal defect classification, ODC)所屬故障被激活后所產(chǎn)生的程序差錯(cuò)形式隨程序?qū)崿F(xiàn)的不同而不同[1],可能以返回碼或共享變量的形式存在于應(yīng)用程序與其使用的庫函數(shù)之間[2,6],也可能以異常的形式在程序中進(jìn)行傳播[5-6],或以跳轉(zhuǎn)指令的組合形式出現(xiàn)[7].
在具有異常處理機(jī)制的程序中,故障激活后所產(chǎn)生的差錯(cuò)若被異常處理機(jī)制偵測(cè),則異常發(fā)生[8-9].若對(duì)該異常處理不當(dāng),則可引起程序失效[9].這一過程將形成“故障-差錯(cuò)-異常-失效”鏈.
通過對(duì)程序異??刂屏?exception control flow,ECF)的分析可收集能夠引起異常的差錯(cuò)信息,包括:由異常類型獲取差錯(cuò)內(nèi)容;由異常引發(fā)點(diǎn)獲取差錯(cuò)被偵測(cè)時(shí)的物理位置;由異常傳播路徑獲取差錯(cuò)的影響范圍;由異常捕捉情況獲取差錯(cuò)是否得到修正的信息.這些信息可指導(dǎo)軟件故障注入方案生成所需的差錯(cuò)類型、注入位置、注入時(shí)機(jī)的選擇[4-5,10-11].該過程通過源代碼的靜態(tài)分析,可在相對(duì)較短的時(shí)間內(nèi)完成.
本文的主要工作是通過故障注入實(shí)驗(yàn)分析程序的“故障-差錯(cuò)-異常”的傳播機(jī)理;結(jié)合函數(shù)級(jí)ECF(function-level ECF,F(xiàn)ECF)的描述,分析了同一差錯(cuò)與多個(gè)程序ECF之間的關(guān)系,利用ECF對(duì)程序中潛在可引起異常的差錯(cuò)進(jìn)行分析,建立了EPB模型;實(shí)現(xiàn)了一個(gè)自動(dòng)分析工具軟件,并以O(shè)penStack的核心組件為對(duì)象進(jìn)行了實(shí)驗(yàn)驗(yàn)證.
Christmansson等[3]認(rèn)為只有注入具有代表性的差錯(cuò)才能有效地模擬真實(shí)故障的發(fā)生,有效地驗(yàn)證軟件的容錯(cuò)機(jī)制.考慮應(yīng)用程序和函數(shù)庫之間的潛在錯(cuò)誤的故障注入工具LFI(庫文件故障注入器)改善了應(yīng)用程序的健壯性測(cè)試技術(shù)[2].基于窮盡異常模擬模式的測(cè)試方法結(jié)合異常發(fā)生的時(shí)序特點(diǎn)在異常引發(fā)點(diǎn)注入異常,簡化了異常處理結(jié)構(gòu)有效性驗(yàn)證的過程[5].上述工作強(qiáng)調(diào)了故障/差錯(cuò)數(shù)據(jù)的有效性,討論了如何利用差錯(cuò)數(shù)據(jù)進(jìn)行軟件容錯(cuò)機(jī)制的驗(yàn)證,但其尚未涉及如何有效地收集合理的差錯(cuò)數(shù)據(jù).
關(guān)于軟件故障激活后的傳播過程及證明故障激活后能否轉(zhuǎn)化為差錯(cuò)的研究,有基于“故障-差錯(cuò)-失效”的傳播關(guān)系選擇具有代表性的差錯(cuò)集合的方法[5].通過代碼內(nèi)部的故障注入和接口差錯(cuò)注入的實(shí)驗(yàn)研究結(jié)果表明,兩者對(duì)程序的影響存在一定的差異[4].代碼故障激活后的差錯(cuò)不僅能以返回值、錯(cuò)誤碼、傳入/傳出參數(shù)的方式進(jìn)行傳播,還能以共享內(nèi)存數(shù)據(jù)為載體對(duì)程序造成影響[11].應(yīng)從多維度對(duì)故障注入后的EPB進(jìn)行收集、分析、歸類,從而使得各層次的EPB研究可得到相關(guān)數(shù)據(jù)的支撐,實(shí)驗(yàn)表明,故障激活后所產(chǎn)生的差錯(cuò)能以返回值或異常形式進(jìn)行傳播,且該差錯(cuò)被偵測(cè)的情況和是否引起程序失效取決于程序的實(shí)現(xiàn)[6].這些工作均未深入研究具有異常處理機(jī)制的程序中的“故障-差錯(cuò)-異?!边^程.
大多數(shù)與程序ECF相關(guān)的研究工作主要聚焦在它對(duì)程序分析、開發(fā)、測(cè)試的影響上.如基于異常傳播分析的C++程序數(shù)據(jù)流分析方法[12]、依賴性分析方法[13].Harrold等[14-15]在對(duì)異常處理機(jī)制的測(cè)試標(biāo)準(zhǔn)進(jìn)行研究時(shí),考慮了異常處理機(jī)制和異常傳播對(duì)程序控制流、數(shù)據(jù)流、控制依賴性等分析技術(shù)的影響.用于程序開發(fā)、維護(hù)、測(cè)試的系統(tǒng)化方法通過分析顯式ECF,總結(jié)了與異常處理結(jié)構(gòu)實(shí)現(xiàn)相關(guān)的編程錯(cuò)誤模式,可指導(dǎo)開發(fā)者如何有效地避免異常處理機(jī)制的錯(cuò)誤使用[16].面向切面機(jī)制在一些情景下會(huì)使異常處理結(jié)構(gòu)的實(shí)現(xiàn)復(fù)雜化,從而降低系統(tǒng)的可靠性[17].Jo等[18]提出了一種基于集合分析的函數(shù)級(jí)別上的Java未捕捉異常分析方法.結(jié)合運(yùn)行時(shí)異常的靜態(tài)測(cè)試方法通過交替執(zhí)行缺陷檢測(cè)及控制流擴(kuò)展,提高了測(cè)試充分度,還分析了運(yùn)行時(shí)異常對(duì)軟件靜態(tài)測(cè)試的影響[19].這些與程序ECF相關(guān)的研究工作并未考慮到異常本身就是程序錯(cuò)誤的一種表象,所以沒有利用異常相關(guān)的信息來分析潛在的EPB.
異常處理機(jī)制(exception handling mechanism,EHM)是程序錯(cuò)誤處理的常用手段之一.當(dāng)程序中EHM偵測(cè)到差錯(cuò)且引發(fā)異常之后,程序的“故障-差錯(cuò)-異常/失效”過程如圖1所示.
對(duì)Android上約800個(gè)應(yīng)用組件所進(jìn)行的600萬次基于外界輸入的健壯性測(cè)試實(shí)驗(yàn)數(shù)據(jù)表明,約10%的應(yīng)用組件發(fā)生了崩潰且均由未捕捉到的異常所造成[6].
本文以分布式網(wǎng)絡(luò)基準(zhǔn)程序Ipbench和OpenStack中的核心組件nova為對(duì)象,結(jié)合ODC故障類型及其分布數(shù)據(jù),以代碼變異的方式實(shí)施故障注入實(shí)驗(yàn),實(shí)驗(yàn)結(jié)果見表1(表中的E表示可引起異常的故障數(shù)量).
在Ipbench中共注入348個(gè)故障,其中255個(gè)故障導(dǎo)致了程序崩潰,且249次崩潰是由未捕捉異常引起.
在nova中共注入1 018個(gè)故障,未出現(xiàn)程序崩潰現(xiàn)象.由表1可知,419個(gè)故障激活后的差錯(cuò)得到程序的修正,可能的原因有:① 有差錯(cuò)的數(shù)據(jù)在被使用之前重新得到初始化;② 有差錯(cuò)程序的執(zhí)行結(jié)果與無差錯(cuò)程序的執(zhí)行結(jié)果一致;③ 差錯(cuò)引起異常且被捕獲,異常處理例程提供了正確的服務(wù).
表1 故障注入實(shí)驗(yàn)結(jié)果Tab.1 Results of fault-injection experiments
以nova的_validate_cell函數(shù)為例,程序的“故障-差錯(cuò)-異常”傳播過程分析如下:
(1) 故障激活所發(fā)生的差錯(cuò)直接引發(fā)異常.如圖2所示,故障激活后的差錯(cuò)直接在當(dāng)前函數(shù)內(nèi)使raise語句得到執(zhí)行,從而引發(fā)異常.同時(shí),圖2中場景a)與b)的故障激活后均引起了同一異常,說明程序中故障與異常存在多對(duì)一關(guān)系,即多個(gè)故障激活后的差錯(cuò)最終均以同一異常在程序中進(jìn)行傳播.
(2) 故障激活所發(fā)生的差錯(cuò)經(jīng)過傳播后引發(fā)異常.圖3所示的故障激活后的差錯(cuò)通過數(shù)據(jù)流影響控制流,最終使得raise語句得到執(zhí)行,引發(fā)異常.
(3) 在程序無故障的情況下,外界輸入或外界資源違反軟件規(guī)約而導(dǎo)致異常發(fā)生.
因此,可從“異常”層次出發(fā),分析程序中可引起異常的差錯(cuò)信息及其對(duì)程序行為的影響,達(dá)到分析與異常相關(guān)的EPB的目的.
圖2 差錯(cuò)直接引起異常例子Fig.2 Example of an error raises exception directly
為了獲取可引起異常的差錯(cuò)的信息,本文方法并不需要構(gòu)建帶有程序ECF的完整過程間控制流[20],而只需獲取獨(dú)立的ECF信息,包括:ECF起始與中止位置信息;ECF對(duì)應(yīng)的異常類型;異常是否被捕捉;ECF所影響到的函數(shù);ECF所影響到的程序功能或服務(wù).這是一種基于源代碼靜態(tài)分析的方法,如何選擇起始函數(shù)作為分析的起始點(diǎn),則直接影響到了分析結(jié)果的有效性.
圖4所示的是函數(shù)級(jí)異常傳播過程,其中nk(1≤k≤m,m≥1)表示函數(shù),其他符號(hào)的意思在圖中已經(jīng)加以說明.以函數(shù)為粒度的異常傳播過程可分為A,B和C三類.
(1) 過程A:異常在當(dāng)前函數(shù)nm被引發(fā),而且被捕捉.
(2) 過程B:異常在當(dāng)前函數(shù)nm被引發(fā),且沿著函數(shù)調(diào)用棧經(jīng)過m-k逆向傳播后在函數(shù)nk中被捕捉,1≤k≤m.
(3) 過程C:異常在當(dāng)前函數(shù)nm被引發(fā),且沿著函數(shù)調(diào)用棧經(jīng)過m-1次逆向傳播,變成未捕捉異常.
圖3差錯(cuò)經(jīng)過傳播而引起異常的例子
Fig.3Exampleofanerrorraisesexceptionwithcertainpropagation
圖4 函數(shù)級(jí)的異常傳播過程Fig.4 Exception propagation process at function level
定義1程序P中由raise/throw語句顯式引起的FECF可表示為5元組Ψ=
(1)ol=(n,lo)為Ψ的起始位置,表示Ψ由函數(shù)no中代碼行號(hào)為lo的raise/throw語句所引發(fā).
(2)t為Ψ所對(duì)應(yīng)的異常類型.
(3)z=(nz,lz)為Ψ的終止位置.若Ψ屬于過程A或B,則nz為Ψ被捕捉時(shí)所在的函數(shù),其對(duì)應(yīng)的異常捕捉語句的行號(hào)為lz;若Ψ屬于過程C,則Ψ在程序P的函數(shù)nz處終止且傳播出去,lz為Ψ進(jìn)入函數(shù)nz時(shí)的異常入口所對(duì)應(yīng)的語句的代碼行號(hào).
(4)π以路徑的形式給出了Ψ的傳播過程.若Ψ屬于過程A或B,則π為no→nm→…→n1→nz,其中no,nz,nk(k=1,2,…,m,m≥1)為Ψ所影響到的函數(shù);若Ψ屬于過程C,則π為no→nm→…→n1→nz→nout,其中nout為占位符,表示該路徑對(duì)應(yīng)的ECF未被捕捉.
(5)e為Ψ被引發(fā)時(shí)程序P的棧底函數(shù),表示被Ψ影響到的程序功能或服務(wù).
與文獻(xiàn)[4, 20]一致,本文也將入口函數(shù)(entry function, EF)作為函數(shù)調(diào)用鏈的分析起點(diǎn),計(jì)算程序中所有潛在的FECF.
同一差錯(cuò)可引起不同的FECF.這些FECF組成的集合稱為FECF簇,對(duì)于其中的任意Ψi與Ψj,它們具有相同的o與t值.
根據(jù)“故障-差錯(cuò)-異?!眰鞑C(jī)理,若故障激活后的差錯(cuò)引起異常,則該故障對(duì)程序帶來的影響完全可由相應(yīng)的FECF簇表示.所以,可通過分析各FECF簇,反向推導(dǎo)程序中可引起異常的各個(gè)差錯(cuò)及其對(duì)程序行為的影響,從“異?!睂哟畏治雠c異常相關(guān)的EPB,收集可引起異常的差錯(cuò)集合.
(3)w為一權(quán)值,即:
(1)
觀察1w值越大,則EPB對(duì)程序可靠性造成危害的風(fēng)險(xiǎn)越大.
異常傳播過程B與C的發(fā)生會(huì)使程序的過程間控制流中產(chǎn)生潛在的非返回調(diào)用[15],它的數(shù)量(即w值)越大,就意味著異常的傳播范圍越大,所以程序的控制流、數(shù)據(jù)流在錯(cuò)誤狀態(tài)下受到的影響越大.
算法Gen_FECF: 計(jì)算一個(gè)FECF實(shí)例
輸入s: 函數(shù)m中的raise/throw語句
m: 語句s所位于的函數(shù)
輸出Ψ: 一個(gè)FECF實(shí)例
聲明 callstack: 遍歷分析函數(shù)調(diào)用鏈時(shí)所維護(hù)的函數(shù)調(diào)用棧
CTS(m): 函數(shù)m的調(diào)用者(caller)調(diào)用函數(shù)m時(shí)所使用的函數(shù)調(diào)用語句
開始 Gen_FECF(s,m)
1. 新建Ψ實(shí)例并設(shè)置其屬性:o←(m,s的行號(hào)),t←s對(duì)應(yīng)的異常類型,π設(shè)置為m,e←callstack的棧底函數(shù);
2. If SLEGS(s)存在c可捕捉由s引發(fā)的異常 then
3.z←(m,c的代碼行號(hào)),m加入π:m→m;
4. returnΨ;
5. else then //當(dāng)前函數(shù)m無法捕捉該異常
6. temp_stack為callstack的副本;
7.send←s; //用于暫存Ψ終止時(shí)的語句
8. While temp_stack不為空:
9.mtop←temp_stack.top();
10. temp_stack.pop();
11. if m!=mtopthen 將mtop加入πendif
12. if temp_stack is empty: //未捕捉異常
13.z←(mtop,send的行號(hào));
14. ifm!=mtopthen
15. 將nout加入π;
16. else
17. 將m→nout加入π;
18. endif
19. returnΨ;
20. else if SLEGS(CTS(mtop))有c可捕捉then
21.z←(temp_stack.top(),c的行號(hào));
22. 將temp_stack.top()加入π;
23. returnΨ;
24. endif
25.send←CTS(mtop) ;
26. endwhile
27. endif
結(jié)束Gen_FECF
在計(jì)算所有FECF時(shí),e可用于表示FECF所影響到的程序功能或服務(wù).
若在函數(shù)遞歸過程中出現(xiàn)異常,則異常在該部分的傳播路徑呈現(xiàn)一定的模式.所以,可根據(jù)該模式制定合理的裁剪規(guī)則,對(duì)遞歸部分的調(diào)用鏈進(jìn)行裁剪,使得分析過程能夠有效地繼續(xù)執(zhí)行下去.
在算法Gen_FECF中,函數(shù)調(diào)用棧是根據(jù)函數(shù)調(diào)用鏈生成的.由于調(diào)用鏈經(jīng)過了遞歸調(diào)用鏈裁減處理,并且調(diào)用鏈中所有函數(shù)都屬于程序P,函數(shù)調(diào)用棧的深度最多為2·|FDS(P)|-2,其中FDS(P)為定義于程序P中且在程序P中實(shí)現(xiàn)的函數(shù)集合.算法Gen_FECF在最好情況下的時(shí)間復(fù)雜度為O(1),在最壞情況下為O(|FDS(P)|).
根據(jù)EHM的性質(zhì)[14],對(duì)于異常的傳播及其處理過程,異常保護(hù)區(qū)z(try語句所保護(hù)的代碼塊)的異常保護(hù)序列EGS(z)指的是z對(duì)應(yīng)的異常處理例程所組成的有序序列(c1,c2,…,cn),n≥1,其順序由z對(duì)應(yīng)的異常處理例程的順序決定.假如zj嵌套于zi之中,那么傳播到zj中的異常首先會(huì)被EGS(zj)中的異常處理例程嘗試捕捉處理,若該異常未被捕捉,則EGS(zi)再嘗試對(duì)其捕捉處理,則LEGS(zj)=(cj1,cj2,…,cjn,ci1,ci2,…,cim),若zi不嵌套于任何異常保護(hù)區(qū)中,則LEGS(zi)=EGS(zi)=(ci1,ci2,…,cim),m≥1,n≥1.若語句s位于z中,則語句s受到LEGS(z)的保護(hù),記為SLEGS(z).若有異常在s(raise/throw語句)處被拋出或異常傳播至s(函數(shù)調(diào)用語句)處,若SLEGS(s)能捕捉該異常,則該異常在s語句所在的函數(shù)中被捕捉,否則該異常從當(dāng)前函數(shù)傳播出去且沿著函數(shù)調(diào)用棧逆向傳播.
在形如(m1,m2, …,mn-1,mn)所表示的調(diào)用棧中,m1表示棧底,mn表示棧頂,n≥1.suc(mi)是mi的后繼mi+1,n≥i≥1,suc(mn)=null.CTS(suc(mk))為函數(shù)mk中調(diào)用函數(shù)suc(mk)時(shí)的函數(shù)調(diào)用語句,且CTS(null) =null.為不失一般性,調(diào)用鏈的遞歸裁剪遵循如下規(guī)則.
規(guī)則1設(shè)當(dāng)前函數(shù)調(diào)用棧具有以下形式:(mbottom, …,M1,M2, …,Mn,M11,M12, …,M1n, …,Mk1,Mk2, …,Mkn, …,Mq1,Mq2, …,Mqp,mother, …),其中,Mkn表示函數(shù)Mn的第k次遞歸調(diào)用,k≥1.Mqp表示函數(shù)Mp第q次遞歸調(diào)用,q>k,n≥p≥0.若?i,j,k≥i,j≥1,式(2)得到滿足,則調(diào)用??刹眉魹?mbottom, …,M1,M2, …,Mn,Mq1,Mq2, …,Mqp,mother, …),且FECF的o、t、z、e屬性值保持不變,π中受到FECF影響的函數(shù)及其順序不變.
SLEGS(CTS(Mi1))=SLEGS(CTS(Mj1))=SLEGS(CTS(Mq1))
SLEGS(CTS(Mi2))=SLEGS(CTS(Mj2))=SLEGS(CTS(M2))
(2)
SLEGS(CTS(Min))=SLEGS(CTS(Mjn))=SLEGS(CTS(Mn))
證明.
情形一:若在Mkn中無異常發(fā)生,n≥1,則無FECF的生成受到裁剪動(dòng)作的影響.
情形二:假如異常x在函數(shù)Mkn中由raise/throw語句引發(fā),k≥1,n≥1:① 若x在Mkn中捕捉,則會(huì)有與異常x相同的異常在函數(shù)Mn中由相同的raise/throw語句引發(fā)且被相同catch/except語句捕捉,因?yàn)镸kn與Mn為相同函數(shù).② 若x從Mkn傳播出去,則會(huì)有與異常x相同的異常在函數(shù)Mn中由相同的raise/throw語句引發(fā)且從相同的異常出口從Mn傳播出去,因?yàn)镸kn與Mn為相同函數(shù).
情形三:假如異常x通過CTS(suc(Mkn))語句從suc(Mkn)函數(shù)傳播至Mkn中,k≥1,n≥1:① 若x在Mkn中捕捉,則會(huì)有與異常x相同的異常y通過CTS(suc(Mn))語句從suc(Mn)傳播至Mn,且在Mn中由相同的catch/except語句捕捉.因?yàn)閟uc(Mn)與suc(Mkn)為相同函數(shù),CTS(suc(Mn))與CTS(suc(Mkn))為同一函數(shù)調(diào)用語句,且SLEGS(CTS(suc(Mn))) =SLEGS(CTS(suc(Mkn))).② 若x從Mkn中傳播出去,則會(huì)有異常x相同的異常y從Mn中的相同異常出口傳播出去.因?yàn)閟uc(Mn)與suc(Mkn)為相同函數(shù),CTS(suc(Mn))與CTS(suc(Mkn))為同一函數(shù)調(diào)用語句,且SLEGS(CTS(suc(Mn))) =SLEGS(CTS(suc(Mkn))).
2. 將調(diào)用棧callStack初始化為空;
3. Traverse_Invocation_Chain(m);
4. endfor
/*遍歷以m開始的函數(shù)調(diào)用鏈,用Gen_FECF算法生成FECF實(shí)例*/
聲明 Traverse_Invocation_Chain (m)
1. callstack.push(m); //維護(hù)調(diào)用棧,m入棧
2. for each 語句sinmthen
3. ifs是raise/throw語句then
4.Ψ←Gen_FECF(s,m);
6. else ifs是調(diào)用函數(shù)mcallee的語句then
7. ifmcallee在callstack出現(xiàn)過兩次and
8. SLEGS(CTS(mcallee))=SLEGS(s) then
9. continue; //滿足要求,裁剪
10. else then //繼續(xù)分析調(diào)用鏈
11. Traverse_Invocation_Chain (mcallee);
12. endif
13. endif
14. end for
15. Callstack.pop(m) //維護(hù)調(diào)用棧,m出棧
2. existEPB← null
4. IfΨ.o=Ω.oandΨ.t=Ω.tthen
5. existEPB ←Ω; break;
6. endif
7. endfor
8. if null = existEPB then //暫無相應(yīng)FECF簇
13. else then //將Ψ加入對(duì)應(yīng)簇的EPB實(shí)例
14. existEPB.w← existEPB.w+φ(Ψ);
17. endif
18. endfor
采用本文提出的方法,用Python語言編寫了一個(gè)基于Understand的EPB自動(dòng)分析工具,其架構(gòu)如圖5所示.Understand是一款代碼審核工具,提供了可操作源代碼相關(guān)數(shù)據(jù)的API,如詞法、語法、函數(shù)調(diào)用關(guān)系等信息.
圖5 EPB自動(dòng)分析工具架構(gòu)Fig.5 Structure of automatic analysis tool of EPB
分析控制器:控制整個(gè)分析過程,包括:調(diào)用鏈的遍歷分析、局部視圖數(shù)據(jù)生成、FECF數(shù)據(jù)生成、EPB數(shù)據(jù)生成、函數(shù)調(diào)用棧的維護(hù)等.
局部視圖生成器: 函數(shù)代碼中與FECF生成相關(guān)的數(shù)據(jù)以文件形式存儲(chǔ),內(nèi)容包括: ① raise/throw語句的位置、對(duì)應(yīng)的異常類型;② 在當(dāng)前函數(shù)被引發(fā)的異常捕捉情況,記錄捕捉該異常的catch/except語句的位置及其對(duì)應(yīng)的異常類型;③ 當(dāng)前函數(shù)的函數(shù)調(diào)用關(guān)系信息;④ 當(dāng)前函數(shù)中的函數(shù)調(diào)用語句是否處于異常保護(hù)區(qū)中,若是,則記錄相應(yīng)的catch/except語句位置及其對(duì)應(yīng)的異常類型.
FECF生成器:當(dāng)異常以raise/throw形式被引發(fā)時(shí),結(jié)合相應(yīng)的局部視圖數(shù)據(jù),根據(jù)Gen_FECF算法生成相應(yīng)FECF數(shù)據(jù).
自動(dòng)分析工具進(jìn)行EPB分析的主要步驟如下:
(1) 以源代碼為輸入,使用Understand軟件生成程序的詞法、語法、函數(shù)調(diào)用關(guān)系等數(shù)據(jù).
(2) 以s為分析起點(diǎn),s∈SEF,迭代分析其函數(shù)調(diào)用鏈,檢查函數(shù)內(nèi)是否有被raise/throw語句引發(fā)的異常.若存在異常,則轉(zhuǎn)(3);否則,繼續(xù)按照(2)分析函數(shù)調(diào)用鏈中未被分析的函數(shù),直到所有調(diào)用鏈分析完畢,轉(zhuǎn)(4).
為了驗(yàn)證本文方法及所開發(fā)的程序EPB自動(dòng)分析工具的合理性和有效性,以O(shè)penStack的核心組件作為對(duì)象進(jìn)行了實(shí)驗(yàn).
實(shí)驗(yàn)在虛擬機(jī)上進(jìn)行,操作系統(tǒng)為內(nèi)核版本2.6.32的32位Linux,硬件配置為1GB內(nèi)存,Intel(R) Core(TM) i3-3217U@1.80GHz單核CPU.實(shí)驗(yàn)負(fù)載為OpenStack(G 版本)中的5個(gè)核心組件,該軟件用Python語言編寫,各組件的SEF數(shù)據(jù)均根據(jù)相應(yīng)的應(yīng)用程序編程接口(application programming interface, API)文檔人工收集而得.
對(duì)27 876行OpenStack組件的錯(cuò)誤行為的實(shí)驗(yàn)結(jié)果見表2,其中duser=10 000表示用戶指定的閾值.
表2 OpenStack組件錯(cuò)誤行為分析結(jié)果Tab.2 Analysis results of erroneous OpenStack component behavior
調(diào)用鏈中函數(shù)調(diào)用點(diǎn)總量與函數(shù)數(shù)量的比值為10 408/1 426=7.3,說明每個(gè)函數(shù)平均被調(diào)用了7.3次,若差錯(cuò)在函數(shù)中引起異常,則該異??蓾撛谝鹩?個(gè)不同ECF組成的FECF簇,表明從異常角度對(duì)差錯(cuò)及其對(duì)程序行為影響進(jìn)行分析是可行的.
圖6 nova組件中以w排序的前十個(gè)EPB實(shí)例數(shù)據(jù)Fig.6 Top ten EPB Ω ordered by w in nova components
本文通過故障注入實(shí)驗(yàn)研究了具有EHM的程序的軟件故障、差錯(cuò)、異常之間的傳播機(jī)理.結(jié)合FECF的描述,說明了如何利用ECF收集與異常相關(guān)的差錯(cuò)信息,建立了基于ECF的EPB模型,開發(fā)了基于該模型的EPB自動(dòng)分析工具,并用該工具對(duì)OpenStack核心組件進(jìn)行了錯(cuò)誤行為分析,結(jié)果表明了基于ECF的EPB分析的合理性和有效性.該方法及其工具為具有EHM的大規(guī)模程序的EPB自動(dòng)分析,指導(dǎo)程序異常處理結(jié)構(gòu)的重構(gòu),使程序可精確捕捉異常,提高程序可靠性,并為構(gòu)造合理的外部激勵(lì)精確激活差錯(cuò),縮短故障注入實(shí)驗(yàn)周期提供了有效手段.