本發(fā)明涉及軟件調(diào)試,特別涉及一種代碼異常定位與處理方法。
背景技術(shù):
軟件調(diào)試在整個軟件開發(fā)中占據(jù)相當(dāng)大的開銷。盡管軟件企業(yè)在軟件調(diào)試中已經(jīng)投入巨資,但軟件發(fā)行后仍然會被發(fā)現(xiàn)有嚴(yán)重的錯誤。在發(fā)行后再對軟件錯誤進(jìn)行修補(bǔ),仍會造成嚴(yán)重的經(jīng)濟(jì)損失。研究發(fā)現(xiàn),與軟件相關(guān)的安全事件,其中大都是由在設(shè)計(jì)或者編碼階段引入的軟件錯誤引起的。但確定一個靜態(tài)源碼檢測到的錯誤是否是一個真實(shí)的錯誤需要花費(fèi)大量的精力。對于軟件錯誤的自動化檢測和修補(bǔ),現(xiàn)有技術(shù)存在以下方案,即不關(guān)心待測程序的內(nèi)部執(zhí)行情況,隨機(jī)的產(chǎn)生用例,觀察程序輸出是否與預(yù)期的相符合,但其缺陷是代碼覆蓋率低,因此其錯誤檢測能力有限。
技術(shù)實(shí)現(xiàn)要素:
為解決上述現(xiàn)有技術(shù)所存在的問題,本發(fā)明提出了一種代碼異常定位與處理方法,包括:
生成用例,然后向路徑約束條件中輸入錯誤約束;
求解新的路徑約束條件,產(chǎn)生觸發(fā)軟件錯誤的用例;
對外部函數(shù)進(jìn)行建模,監(jiān)控外部函數(shù)導(dǎo)致的符號傳遞;
通過符號傳遞定位代碼錯誤。
優(yōu)選地,所述求解新的路徑約束條件,產(chǎn)生觸發(fā)軟件錯誤的用例,進(jìn)一步包括,檢測當(dāng)前運(yùn)行路徑上的錯誤的錯誤約束,在當(dāng)前運(yùn)行路徑下當(dāng)錯誤約束滿足時,則觸發(fā)錯誤,且得到的解就是保證觸發(fā)錯誤的用例。
優(yōu)選地,所述方法還包括:對待測程序進(jìn)行監(jiān)控,當(dāng)關(guān)鍵指令被執(zhí)行時,主動在路徑約束條件中輸入錯誤約束,并對錯誤約束進(jìn)行標(biāo)記。
優(yōu)選地,當(dāng)所述代碼錯誤為數(shù)組越限時,檢測數(shù)組越限錯誤,追蹤符號傳遞,當(dāng)有符號作為索引對數(shù)組進(jìn)行訪問時,查詢當(dāng)前棧幀范圍,獲得數(shù)組邊界,生成違反數(shù)組邊界要求的錯誤約束,并輸入到當(dāng)前的路徑約束條件中;當(dāng)新的路徑約束條件滿足時,則觸發(fā)數(shù)組越限錯誤;追蹤符號從其他變量傳遞到數(shù)組的索引;數(shù)組操作識別,即通過逆向分析,將x86架構(gòu)下的數(shù)組操作通過調(diào)整編譯選項(xiàng)而使得所有的數(shù)組操作都編譯為基址變址操作;檢測數(shù)組的合法范圍,如果數(shù)組操作在合法范圍內(nèi)則是合法的數(shù)組操作,否則數(shù)組越限,具體包括先進(jìn)行反匯編,再反編譯,獲得具有數(shù)據(jù)結(jié)構(gòu)信息的中間表達(dá)形式,再在中間表達(dá)形式的基礎(chǔ)上進(jìn)行數(shù)組識別,識別數(shù)組后使用棧幀范圍來作為數(shù)組邊界的近似。
本發(fā)明相比現(xiàn)有技術(shù),具有以下優(yōu)點(diǎn):
本發(fā)明提出了一種代碼異常定位與處理方法,在不降低代碼覆蓋率的前提下,提高了錯誤定位效率,優(yōu)化了代碼錯誤搜索過程。
附圖說明
圖1是根據(jù)本發(fā)明實(shí)施例的代碼異常定位與處理方法的流程圖。
具體實(shí)施方式
下文與圖示本發(fā)明原理的附圖一起提供對本發(fā)明一個或者多個實(shí)施例的詳細(xì)描述。結(jié)合這樣的實(shí)施例描述本發(fā)明,但是本發(fā)明不限于任何實(shí)施例。本發(fā)明的范圍僅由權(quán)利要求書限定,并且本發(fā)明涵蓋諸多替代、修改和等同物。在下文描述中闡述諸多具體細(xì)節(jié)以便提供對本發(fā)明的透徹理解。出于示例的目的而提供這些細(xì)節(jié),并且無這些具體細(xì)節(jié)中的一些或者所有細(xì)節(jié)也可以根據(jù)權(quán)利要求書實(shí)現(xiàn)本發(fā)明。
本發(fā)明的一方面提供了一種代碼異常定位與處理方法。圖1是根據(jù)本發(fā)明實(shí)施例的代碼異常定位與處理方法流程圖。
本發(fā)明在代碼檢測系統(tǒng)中,通過產(chǎn)生用例而再現(xiàn)錯誤,向路徑約束條件中輸入錯誤約束,通過求解新的路徑約束條件,產(chǎn)生觸發(fā)軟件錯誤的用例;然后對外部函數(shù)進(jìn)行建模,監(jiān)控外部函數(shù)導(dǎo)致的符號傳遞,而不增加約束,基于改進(jìn)的優(yōu)化路徑遍歷搜索方法更快地執(zhí)行到錯誤路徑,從而能夠更快地檢測到代碼錯誤。
代碼檢測系統(tǒng)檢測當(dāng)前運(yùn)行路徑上的錯誤的錯誤約束,在當(dāng)前運(yùn)行路徑下當(dāng)錯誤約束滿足時,則觸發(fā)錯誤,且得到的解就是能保證觸發(fā)錯誤的用例。代碼檢測系統(tǒng)對待測程序進(jìn)行監(jiān)控,當(dāng)關(guān)鍵指令被執(zhí)行時,主動在路徑約束條件中輸入錯誤約束,并對錯誤約束進(jìn)行標(biāo)記。
代碼檢測系統(tǒng)包括多個錯誤檢測單元,分別支持不同類型的錯誤檢測:數(shù)組越限、除零錯誤、空指針引用錯誤、函數(shù)參數(shù)錯誤。數(shù)組越限檢測單元用于檢測數(shù)組越限錯誤,追蹤符號傳遞,當(dāng)有符號作為索引對數(shù)組進(jìn)行訪問時,查詢當(dāng)前棧幀范圍,獲得數(shù)組邊界,生成違反數(shù)組邊界要求的錯誤約束,并輸入到當(dāng)前的路徑約束條件中;當(dāng)新的路徑約束條件滿足時,則觸發(fā)數(shù)組越限錯誤。該數(shù)組越限檢測單元還用于符號索引追蹤,即追蹤符號從其他變量傳遞到數(shù)組的索引;數(shù)組操作識別,即通過逆向分析,將x86架構(gòu)下的數(shù)組操作通過調(diào)整編譯選項(xiàng)而使得所有的數(shù)組操作都編譯為基址變址操作;和數(shù)組邊界檢測,即檢測數(shù)組的合法范圍,如果數(shù)組操作在合法范圍內(nèi)則是合法的數(shù)組操作,否則數(shù)組越限,具體包括先進(jìn)行反匯編,再反編譯,獲得具有數(shù)據(jù)結(jié)構(gòu)信息的中間表達(dá)形式,再在中間表達(dá)形式的基礎(chǔ)上進(jìn)行數(shù)組識別,識別數(shù)組后使用棧幀范圍來作為數(shù)組邊界的近似。除零錯誤檢測單元用于檢測除零錯誤,將div(無符號除)和idiv(帶符號除)兩種指令視為關(guān)鍵指令,當(dāng)符號作為除數(shù)時,生成錯誤約束,并輸入到路徑約束條件中,最后通過求解新路徑約束條件,獲得可以觸發(fā)除零錯誤的用例。代碼檢測系統(tǒng)。空指針引用錯誤檢測單元用于檢測空指針引用錯誤。當(dāng)一個符號作為地址被引用時,判斷地址是否與符號有關(guān),并輸入到路徑約束條件中,通過求解新路徑約束條件,獲得可以觸發(fā)空指針引用錯誤的用例。函數(shù)參數(shù)錯誤檢測單元用于并對需要檢測的函數(shù)插樁,當(dāng)關(guān)鍵函數(shù)被調(diào)用且函數(shù)參數(shù)與符號相關(guān)時則生成錯誤約束,并輸入到路徑約束條件中。為了對關(guān)鍵函數(shù)進(jìn)行插樁,代碼檢測系統(tǒng)利用插樁工具pin對導(dǎo)出關(guān)鍵函數(shù)的映像文件進(jìn)行插樁,當(dāng)映像文件加載時,搜索映像文件中關(guān)鍵函數(shù)的位置,再對關(guān)鍵函數(shù)插樁。
當(dāng)待測程序調(diào)用外部函數(shù)時,代碼檢測系統(tǒng)根據(jù)外部函數(shù)的地址,利用插樁工具提供的api獲得外部函數(shù)名。然后,根據(jù)外部函數(shù)的函數(shù)名判斷該函數(shù)是否有對應(yīng)的函數(shù)模型,如果沒有,則實(shí)際執(zhí)行該函數(shù)。如果有對應(yīng)的函數(shù)模型,判斷函數(shù)的參數(shù)是否與符號相關(guān),如果函數(shù)的參數(shù)與符號相關(guān),則執(zhí)行函數(shù)模型,追蹤符號傳遞,隨后進(jìn)行實(shí)際執(zhí)行。
在路徑遍歷搜索過程中,首先接受初始用例作為其參數(shù)。初始用例的邊界設(shè)置為0,表明執(zhí)行初始用例產(chǎn)生的路徑約束條件從深度0開始都被否定,以產(chǎn)生新的路徑約束條件。將初始用例加入到一個工作列表中;實(shí)際執(zhí)行待測程序,其輸入為初始用例,檢測初始用例能否觸發(fā)錯誤。當(dāng)工作列表不為空時,則進(jìn)入頂層循環(huán)的動態(tài)符號執(zhí)行;依據(jù)是用例的分值,從工作列表中選擇一個用例作為當(dāng)前動態(tài)符號執(zhí)行的輸入,分值越高代表優(yōu)先級越高;對待測程序進(jìn)行動態(tài)符號執(zhí)行,并生成新的用例集合。對集合中每一個用例進(jìn)行實(shí)際執(zhí)行,檢測是否能夠觸發(fā)待測程序的錯誤,并對每個新用例進(jìn)行評分。
為了檢測內(nèi)存函數(shù)錯誤,代碼檢測系統(tǒng)首先將所有的輸入標(biāo)記為可疑點(diǎn),表示所有的輸入都是不可信的,然后追蹤可疑點(diǎn)傳遞,當(dāng)可疑點(diǎn)數(shù)據(jù)作為源操作數(shù)的時候,將指令的目的操作數(shù)也標(biāo)記為可疑點(diǎn)。當(dāng)可疑點(diǎn)數(shù)據(jù)傳遞到內(nèi)存函數(shù)時,即可疑點(diǎn)數(shù)據(jù)作為內(nèi)存函數(shù)的參數(shù)時,則找到了內(nèi)存函數(shù)錯誤。
在可疑點(diǎn)的數(shù)據(jù)結(jié)構(gòu)上,采用一個連續(xù)的內(nèi)存空間。給定一個虛擬地址addr,使用這個地址addr,找到可疑點(diǎn)數(shù)據(jù)結(jié)構(gòu)的字節(jié)位置,再找到字節(jié)中的位偏移。如果這1位為1,表示對應(yīng)的地址addr是可疑點(diǎn)數(shù)據(jù),如果是0則表示該地址不是可疑點(diǎn)數(shù)據(jù)。然后對可疑點(diǎn)傳遞進(jìn)行追蹤。具體包括:注冊一個初始化回調(diào)函數(shù),對追蹤可疑點(diǎn)傳遞所需要的臨時數(shù)據(jù)結(jié)構(gòu)進(jìn)行初始化。該臨時數(shù)據(jù)結(jié)構(gòu)存儲內(nèi)存地址和寬度信息、寄存器、指令操作碼、指令類型。判斷是否是內(nèi)存讀取操作,如果是則根據(jù)讀取的內(nèi)存地址和內(nèi)存操作數(shù)的大小,而將這些信息存儲到臨時數(shù)據(jù)結(jié)構(gòu)中;判斷是否是內(nèi)存修改操作,如果是則根據(jù)修改的內(nèi)存地址和內(nèi)存操作數(shù)的大小而將這些信息存儲到臨時數(shù)據(jù)結(jié)構(gòu)中。獲得讀取的寄存器。將該寄存器信息存儲到臨時數(shù)據(jù)結(jié)構(gòu)中。將該寄存器信息存儲到臨時數(shù)據(jù)結(jié)構(gòu)中。將指令類型和指令操作碼信息存儲到臨時數(shù)據(jù)結(jié)構(gòu)中。到臨時數(shù)據(jù)結(jié)構(gòu)中查找所有被讀取的寄存器和內(nèi)存地址,然后利用上述可疑點(diǎn)數(shù)據(jù)結(jié)構(gòu)中查詢是否是可疑點(diǎn)。如果不是,則將記錄在臨時數(shù)據(jù)結(jié)構(gòu)中的那些被修改的寄存器和內(nèi)存地址的可疑點(diǎn)信息全部刪除。如果有任何一個寄存器或者內(nèi)存地址是可疑點(diǎn),則將記錄在臨時數(shù)據(jù)結(jié)構(gòu)里的那些被修改的寄存器和內(nèi)存地址全都標(biāo)記為可疑點(diǎn)。
對于空指針引用錯誤檢測,本發(fā)明還提供了一種可選的方式:
步驟1:讀取源文件,對其進(jìn)行詞法分析和語法分析,利用輔助工具生成應(yīng)用的語法樹,根據(jù)所述語法樹生成反映應(yīng)用控制結(jié)構(gòu)的控制流圖,并根據(jù)所述語法樹創(chuàng)建應(yīng)用的符號表系統(tǒng)與類型系統(tǒng),基于語法樹識別出應(yīng)用的全部可定位表達(dá)式,具體包括:基于語法樹識別出應(yīng)用的所有定義的符號以及所有使用的可定位表達(dá)式;識別所有定義的函數(shù),并將識別的函數(shù)作為一個符號加入到相應(yīng)作用域中;識別所有定義的結(jié)構(gòu)體與聯(lián)合;并將識別出的結(jié)構(gòu)體與聯(lián)合作為一個符號加入到相應(yīng)作用域中;識別出結(jié)構(gòu)體與聯(lián)合的成員,并加入到相應(yīng)作用域中;識別所有定義的變量;其中,變量的類型為指針時,將變量作為一個指針類型符號添加到相應(yīng)的作用域中,將指針的引用作為一個待識別的變量;變量的類型為數(shù)組時,將變量作為一個數(shù)組類型符號添加到相應(yīng)的作用域中,將數(shù)組的每一個成員作為一個待識別的變量;變量的類型為結(jié)構(gòu)體或聯(lián)合時,將變量作為一個結(jié)構(gòu)體與聯(lián)合類型符號添加到相應(yīng)的作用域中,將結(jié)構(gòu)體與聯(lián)合的每一個成員作為一個待識別的變量;否則,將變量作為一個基本類型符號,添加到相應(yīng)的作用域中?;谡Z法樹識別出應(yīng)用的所有使用的可定位表達(dá)式,包括從語法樹上的后綴表達(dá)式節(jié)點(diǎn)識別所有使用的后綴表達(dá)式;從語法樹上的一元表達(dá)式節(jié)點(diǎn)識別所有使用的指針引用表達(dá)式。
對于識別出的可定位表達(dá)式,通過類型推導(dǎo)規(guī)則推導(dǎo)其類型。對于聲明的標(biāo)志符變量,根據(jù)其聲明可知其類型。對于復(fù)雜數(shù)據(jù)類型的變量:(1)如果是數(shù)組,可知其元素的類型;(2)如果是指針,可知其指向的表達(dá)式的類型;(3)如果是結(jié)構(gòu)體,可知其每個域成員的類型;對于不能通過聲明識別的表達(dá)式,通過類型推導(dǎo)規(guī)則推導(dǎo)出其類型。
步驟2:根據(jù)控制流圖產(chǎn)生時的節(jié)點(diǎn)號順序,取控制流圖中的下一個節(jié)點(diǎn)作為當(dāng)前節(jié)點(diǎn),如果所述當(dāng)前節(jié)點(diǎn)為最后一個節(jié)點(diǎn),則結(jié)束遍歷;所述生成函數(shù)摘要,對所述當(dāng)前節(jié)點(diǎn)上第一次出現(xiàn)的變量,用基于區(qū)域的四元模型<variable,region,expression,domain>對所述變量進(jìn)行建模,并根據(jù)所述變量的類型進(jìn)行初始操作,包括:設(shè)置初始的區(qū)間值;若變量的類型是指針,設(shè)置其指向集合為空;其中,variable為被建模的所述變量,region為所述變量分配的抽象內(nèi)存區(qū)域,expression為符號表達(dá)式,domain為取值區(qū)間;對所述當(dāng)前節(jié)點(diǎn)的前驅(qū)節(jié)點(diǎn)上出現(xiàn)的除作用域的指針之外的每一個指針,求其在所述當(dāng)前節(jié)點(diǎn)的所有前驅(qū)節(jié)點(diǎn)上的指向集合的并集,得到該指針在所述當(dāng)前節(jié)點(diǎn)上的初始指向集合;其中,所述作用域?yàn)榉柋硐到y(tǒng)中的作用域,用于存儲識別出的各類符號;對所述當(dāng)前節(jié)點(diǎn)的前驅(qū)節(jié)點(diǎn)上出現(xiàn)的除作用域的變量之外的每一個變量,求其在所述當(dāng)前節(jié)點(diǎn)的所有前驅(qū)節(jié)點(diǎn)上的取值區(qū)間或區(qū)間集的并集,得到該變量在所述當(dāng)前節(jié)點(diǎn)上的初始取值區(qū)間或初始區(qū)間集,然后判斷在所述當(dāng)前節(jié)點(diǎn)上是否存在某個變量的初始取值區(qū)間或初始區(qū)間集為空,若存在,則標(biāo)記該節(jié)點(diǎn)為矛盾節(jié)點(diǎn);若不存在,則根據(jù)所述當(dāng)前節(jié)點(diǎn)所對應(yīng)的語句類型,對該節(jié)點(diǎn)上每個已獲得初始指向集合的指針進(jìn)行相應(yīng)的指針分析,對該節(jié)點(diǎn)上的每個已獲得初始區(qū)間值或初始區(qū)間集的變量進(jìn)行相應(yīng)的區(qū)間運(yùn)算。其中,當(dāng)變量是基本類型時,用基于區(qū)域的四元模型對其進(jìn)行建模,根據(jù)其具體類型設(shè)置初始區(qū)間;變量是數(shù)組元素時,建立數(shù)組的region與該變量region的父子層次關(guān)系;變量是結(jié)構(gòu)體或聯(lián)合類型時,建立結(jié)構(gòu)體或聯(lián)合的region與該變量的region的父子層次關(guān)系;變量是指針類型時,設(shè)置其指向集合為空,設(shè)置其初始狀態(tài)為unsure。
若所述當(dāng)前節(jié)點(diǎn)所對應(yīng)的語句類型為賦值語句,將指向集合的每一個抽象內(nèi)存區(qū)域,其取值區(qū)間為變量當(dāng)前的取值區(qū)間與右端表達(dá)式取值區(qū)間的并集;如果指向集合的抽象內(nèi)存區(qū)域類型為指針類型,則每一個抽象內(nèi)存區(qū)域的指向集合為當(dāng)前指向集合與右端表達(dá)式指向集合的并集;若所述當(dāng)前節(jié)點(diǎn)所對應(yīng)的語句類型為條件語句,將該變量的每個成員作為一個被賦值變量,將右側(cè)表達(dá)式中的每一個對應(yīng)的成員作為為該成員賦值的右側(cè)表達(dá)式,如果被賦值變量的類型為基本類型,則根據(jù)被賦值變量的類型及右端表達(dá)式計(jì)算該賦值語句中表達(dá)式的取值區(qū)間,并將所述被賦值變量的取值區(qū)間重置為該新計(jì)算出的表達(dá)式的取值區(qū)間;若所述當(dāng)前節(jié)點(diǎn)所對應(yīng)的語句類型為條件判斷語句,則對該節(jié)點(diǎn)所關(guān)聯(lián)的每一指針取初始的可能指向集后,分析該節(jié)點(diǎn)所關(guān)聯(lián)的每一指針在所述條件判斷語句中指向的可能集合和必然集合;對該節(jié)點(diǎn)所關(guān)聯(lián)的每一變量取初始的可能集后,計(jì)算該節(jié)點(diǎn)所關(guān)聯(lián)的每一變量在所述條件判斷語句中的取值的可能集和必然集,進(jìn)而得到該節(jié)點(diǎn)所對應(yīng)的控制流圖中真假分支上的所述變量取值情況;
所述生成函數(shù)摘要具體包括:生成函數(shù)摘要的前置約束條件;識別出需要被約束的、類型為指針的函數(shù)參數(shù)與全局變量;計(jì)算出被約束指針的弱約束條件。分析函數(shù)調(diào)用引起控制流發(fā)生改變的情況;計(jì)算函數(shù)的返回值。分析函數(shù)調(diào)用對指針類型形參與指針類型全局變量的指向關(guān)系與狀態(tài)的更新;分析函數(shù)調(diào)用對全局變量的數(shù)據(jù)流更新。
步驟3:根據(jù)所述函數(shù)摘要以及語法樹識別出全部的指針引用以及被引用的指針,并對每個被引用的指針創(chuàng)建空指針引用缺陷狀態(tài)機(jī)實(shí)例;在語法樹的一元表達(dá)式節(jié)點(diǎn)上識別出指針引用,以及被引用的指針;在語法樹的后綴表達(dá)式節(jié)點(diǎn)上識別出的指針引用,以及被引用的指針;在語法樹的一元表達(dá)式節(jié)點(diǎn)上識別出函數(shù)調(diào)用表達(dá)式;如果函數(shù)調(diào)用表達(dá)式對應(yīng)的被調(diào)用函數(shù)有函數(shù)摘要時,則獲取函數(shù)摘要的前置約束條件,以及所述前置約束條件中全部被約束變量,將與所述被約束變量對應(yīng)的實(shí)參或全局變量作為被引用的指針;如果函數(shù)調(diào)用表達(dá)式對應(yīng)的被調(diào)用函數(shù)沒有函數(shù)摘要時,將傳遞給被調(diào)用函數(shù)的所有指針類型參數(shù)作為被引用的指針。
步驟4:基于控制流圖運(yùn)行空指針引用缺陷狀態(tài)機(jī)實(shí)例,在控制流圖的每個節(jié)點(diǎn)上,根據(jù)區(qū)間運(yùn)算、指針分析的結(jié)果對每個缺陷狀態(tài)機(jī)實(shí)例進(jìn)行狀態(tài)遷移,確定安全指針引用集合、空指針引用集合、不確定的指針引用集合。
其中,賦值表達(dá)式的指針分析與區(qū)間運(yùn)算過程具體包括:
判斷等號左側(cè)表達(dá)式的類型,若等號左側(cè)表達(dá)式為指針解引用,則根據(jù)等號右側(cè)不同表達(dá)式信息進(jìn)行區(qū)間運(yùn)算與指針分析;若等號左側(cè)表達(dá)式為指針變量,則根據(jù)等號右側(cè)不同表達(dá)式信息進(jìn)行區(qū)間運(yùn)算與指針分析;若等號左側(cè)表達(dá)式為復(fù)雜數(shù)據(jù)結(jié)構(gòu)類型,根據(jù)等號右側(cè)不同表達(dá)式信息進(jìn)行區(qū)間運(yùn)算與指針分析;否則,將等號左側(cè)表達(dá)式的類型為基本數(shù)據(jù)類型,根據(jù)等號右側(cè)不同表達(dá)式信息進(jìn)行區(qū)間運(yùn)算與指針分析。
當(dāng)左側(cè)表達(dá)式的類型為基本數(shù)據(jù)類型時,如果右側(cè)是指針解引用,則獲得右側(cè)被引用指針的指向集合,求得指向集合所指向的抽象內(nèi)存區(qū)域的符號取值的并集,將左側(cè)變量的抽象內(nèi)存區(qū)域的符號取值更新為所得并集;否則,將左側(cè)變量的抽象內(nèi)存區(qū)域的符號取值更新為右側(cè)表達(dá)式的符號取值。當(dāng)左側(cè)表達(dá)式的類型為被引用指針時,獲得左側(cè)被引用指針的指向集合,獲得指向集合對應(yīng)的抽象內(nèi)存區(qū)域集合;如果抽象內(nèi)存區(qū)域均已被處理,結(jié)束對左側(cè)是指針解引用的賦值語句的處理;否則,取抽象內(nèi)存區(qū)域集合中一個未被處理的抽象內(nèi)存區(qū)域,然后判斷左側(cè)表達(dá)式類型是否為復(fù)雜數(shù)據(jù)類型,如果是,對抽象內(nèi)存區(qū)域根據(jù)等號右側(cè)不同表達(dá)式信息進(jìn)行區(qū)間運(yùn)算,如果不是,對抽象內(nèi)存區(qū)域根據(jù)等號右側(cè)不同表達(dá)式信息進(jìn)行區(qū)間運(yùn)算與指針分析。左側(cè)表達(dá)式的類型為指針變量時,將左側(cè)指針變量對應(yīng)的抽象內(nèi)存區(qū)域的指向集合置為空;判斷右側(cè)表達(dá)式是否為變量地址,若為變量地址,將右側(cè)地址變量對應(yīng)的抽象內(nèi)存區(qū)域添加到左側(cè)指針的抽象內(nèi)存區(qū)域的指向集合,左側(cè)指針的抽象內(nèi)存區(qū)域的取值為非空;若不為變量地址,分析右側(cè)指針表達(dá)式的指向集合與取值,將右側(cè)表達(dá)式的指向集合賦予給左側(cè)指針的抽象內(nèi)存區(qū)域的指向集合,將右側(cè)表達(dá)式的取值賦值給左側(cè)指針的抽象內(nèi)存區(qū)域的取值。
函數(shù)調(diào)用語句的指針分析與區(qū)間運(yùn)算過程具體包括:獲得被調(diào)用函數(shù)的函數(shù)摘要;獲得函數(shù)摘要的后置約束條件,獲得后置約束條件中產(chǎn)生了副作用的引用類型的函數(shù)參數(shù)與全局變量;對產(chǎn)生了副作用的引用類型的函數(shù)參數(shù)與全局變量,基于后置約束條件更新其區(qū)間取值與指向信息。
在進(jìn)行過程間分析創(chuàng)建函數(shù)摘要時,考慮到全部的被分析函數(shù)作用域內(nèi)的變量包括頂級變量與成員變量。同時考慮到每個被約束變量的弱約束條件以。因此函數(shù)摘要的前置約束條件約束的變量是被解引用的指針類型的函數(shù)參數(shù)與全局變量、以及它們是指針類型的成員;函數(shù)摘要的后置約束條件是被該函數(shù)副作用影響的對指針類型的參數(shù)與全局變量及它們的成員;函數(shù)摘要的特征信息包括函數(shù)的返回值、控制流終止信息。
在面向?qū)ο蟪绦蛑?,對象是面向?qū)ο蟪绦蜻\(yùn)行時的基本活動單位。因此本發(fā)明另一方面對每個類容器中的語句結(jié)合所屬對象的可疑率信息,區(qū)分不同類中具有相同覆蓋信息語句的可疑率,首先提取對象可疑率信息的提取方法;對象可疑率信息與語句頻率信息的結(jié)合方法。
在可疑率提取過程中,首先執(zhí)行多條失敗用例和多條成功用例,搜集每個對象的過程調(diào)用執(zhí)行軌跡;然后,把每個對象的過程調(diào)用執(zhí)行軌跡劃分為窗口大小為3的過程調(diào)用序列,根據(jù)用例執(zhí)行信息,生成過程調(diào)用序列頻率信息。使用四元組(aep,anp,aef,anf)表示過程調(diào)用序列頻率信息,其中aep,anp分別表示成功用例執(zhí)行和未執(zhí)行過程調(diào)用序列的數(shù)量,aef,anf分別表示失敗用例執(zhí)行和未執(zhí)行過程調(diào)用序列的數(shù)量。
然后,基于過程調(diào)用序列頻率信息以及搜集到的調(diào)試執(zhí)行結(jié)果向量,設(shè)計(jì)度量公式:
其中pass(p)=aep/(anp+aep)表示成功用例執(zhí)行過程調(diào)用序列p的百分比,fail(p)=aef/(anf+aef)表示失敗用例執(zhí)行過程調(diào)用序列p的百分比。
然后,利用上述計(jì)算的過程調(diào)用序列可疑率量化對象的可疑率信息:搜集每個對象的過程調(diào)用序列集合,把屬于同一個類的所有對象的過程調(diào)用序列集合合并為一個類的過程調(diào)用序列集合,該集合描述了該類在程序中的執(zhí)行行為;然后,把類的過程調(diào)用序列集合s(c)的平均可疑率作為該對象的可疑率w(c):
w(c)=∑p∈s(c)w(p)/t;
其中t=為s(c)中元素的個數(shù)。
把每條語句按照基于失敗用例執(zhí)行數(shù)目的分組策略分成若干組。通過分組策略,防止排名靠后的可疑語句結(jié)合對象可疑率信息后排名高于錯誤語句。
根據(jù)分組策略,假設(shè)將可疑語句分為1-n組,標(biāo)記為g0,g1,g2,……,gn-1。gi中的下標(biāo)i表示有i個失敗用例執(zhí)行了gi組內(nèi)的可疑語句。每條可疑語句只包含在一個組內(nèi),可疑語句和組具有多對一的映射關(guān)系。給定語句s,算法的可疑率計(jì)算方式如下。
在上述公式中,tf代表失敗用例的總數(shù),c(s)表示包含語句s的類。w()表示相應(yīng)對象的可疑率,m(s)表示由頻率錯誤定位過程計(jì)算得到的語句s可疑率;并且當(dāng)s∈gi時,ti=1;否則ti=0。
在結(jié)合函數(shù)嵌套路徑信息的錯誤定位中,將函數(shù)嵌套路徑信息與程序頻率信息相結(jié)合,然后提供失效相關(guān)的函數(shù)嵌套路徑信息作為上下文信息,緩解程序頻率信息的局限性對錯誤定位效果的影響。
給定被測程序和相應(yīng)的用例集,首先搜集函數(shù)嵌套邊剖面信息,構(gòu)建加權(quán)的函數(shù)嵌套圖;然后,利用過程間函數(shù)嵌套路徑遍歷搜索算法搜索錯誤語句,對可疑語句在排序中的審查順序進(jìn)行重新定義,并利用函數(shù)嵌套路徑信息將審查的語句關(guān)聯(lián)起來。
給定被測程序以及相應(yīng)的用例集,靜態(tài)分析源代碼,獲得相應(yīng)的函數(shù)嵌套圖。在函數(shù)嵌套圖中,每個節(jié)點(diǎn)表示—個函數(shù),每條邊對一個函數(shù)嵌套關(guān)系。插樁源代碼,執(zhí)行相應(yīng)的用例集,搜集函數(shù)嵌套剖面信息,即每條函數(shù)嵌套邊的執(zhí)行信息。根據(jù)函數(shù)嵌套剖面信息,計(jì)算函數(shù)嵌套圖中每條邊的權(quán)重,建立加權(quán)的函數(shù)嵌套圖?;诩訖?quán)的函數(shù)嵌套圖,按照預(yù)定義遍歷算法搜索錯誤,并記錄搜索錯誤過程中要檢測的可疑語句以及相應(yīng)的函數(shù)嵌套路徑信息。將搜索過程中要審查的可疑語句進(jìn)行定位錯誤。
在已有函數(shù)嵌套圖g(p)=<m,e>的基礎(chǔ)上,eij表示從mi到mj的嵌套關(guān)系。函數(shù)嵌套邊執(zhí)行剖面信息構(gòu)建加權(quán)的函數(shù)嵌套圖。在加權(quán)函數(shù)嵌套圖中,每條函數(shù)嵌套邊具有一個權(quán)重,該權(quán)重表示相鄰兩個函數(shù)節(jié)點(diǎn)關(guān)系的緊密程度。如果用例t執(zhí)行了eij對應(yīng)的函數(shù)嵌套,則記為eij被用例t所覆蓋。給定用例集t=tp∪tf其中表示tp成功調(diào)試用集,tf表示失敗用例集。ep(eij)={θ(eij,t1),θ(eij,t2),…θ(eij,tn)}表示調(diào)用邊eij的執(zhí)行剖面信息。當(dāng)用例tk覆蓋了eij時,θ(eij,tk)=1;反之,θ(eij,tk)=0。成功用例集tp和失敗用例集tf關(guān)于eij執(zhí)行剖面信息分別記為epp(eij)和epf(eij),通過以下方法分別計(jì)算eij關(guān)于成功用例集和失敗用例集的執(zhí)行次數(shù)esp(eij)和esf(eij):
采用esp(eij)和esf(eij)的平均值作為每條調(diào)用邊eij的權(quán)值:
wt(eij)=(esp(eij)和esf(eij))/2
在基于基于加權(quán)的函數(shù)嵌套路徑的搜索時,通過遍歷加權(quán)函數(shù)嵌套圖搜索錯誤語句,同時搜集相關(guān)的函數(shù)嵌套路徑信息作為上下文幫助理解錯誤;重新定義中語句的排序,將獨(dú)立的不相關(guān)的語句進(jìn)行關(guān)聯(lián)。
1.首先按照原排序選擇具有高可疑率的語句,或者屬于同一個函數(shù)的具有相同可疑率的語句,將包含這些語句的函數(shù)入棧,并作為加權(quán)函數(shù)嵌套圖中搜索的起點(diǎn)。
2.基于搜索起始節(jié)點(diǎn),首先深度優(yōu)先搜索它的父節(jié)點(diǎn),最多遍歷三層深度。在遍歷每層函數(shù)節(jié)點(diǎn)時,在該函數(shù)中具有較高可疑率的語句將按照順序進(jìn)行審查,如果檢測的語句中包含錯誤語句,則遍歷算法停止;否則把該函數(shù)節(jié)點(diǎn)入棧,并選擇具有最大權(quán)重的鄰接邊作為要遍歷的下一條邊。當(dāng)沒有邊可以遍歷或者深度己經(jīng)超過3時,回溯到棧中存放的上一個節(jié)點(diǎn)重復(fù)上述遍歷的過程。
3.當(dāng)遍歷完該節(jié)點(diǎn)的父節(jié)點(diǎn),并未搜索到錯誤語句,重復(fù)步驟2中的搜索過程深度優(yōu)先遍歷它的子節(jié)點(diǎn)。
4.記錄這一輪遍歷錯誤語句過程中需要審查的代碼,以及相應(yīng)函數(shù)嵌套路徑信息。如果遍歷完相關(guān)函數(shù)節(jié)點(diǎn)未發(fā)現(xiàn)錯誤語句,則從步驟1開始繼續(xù)這個過程,直到檢查到錯誤語句為止。
對于步驟2和步驟3,在選擇下一條要遍歷的函數(shù)嵌套邊以及每個函數(shù)節(jié)點(diǎn)所要審查的可疑語句時,使用了如下啟發(fā)式過程:
在每次選擇下一個函數(shù)節(jié)點(diǎn)進(jìn)行遍歷時,應(yīng)選擇未遍歷的函數(shù)嵌套邊,以及至少一條失敗用例執(zhí)行了該函數(shù)嵌套邊,而且該函數(shù)嵌套邊具有最大的權(quán)值。在遍歷函數(shù)節(jié)點(diǎn)所包含的可疑語句時,只記錄如下可疑語句:在當(dāng)前函數(shù)節(jié)點(diǎn)里未檢査,而且具有最高可疑率;在排序到這一輪遍歷的起始節(jié)點(diǎn)所記錄語句的排序距離不超過所有語句數(shù)量的10%。
綜上所述,本發(fā)明提出了一種代碼異常定位與處理方法,在不降低代碼覆蓋率的前提下,提高了錯誤定位效率,優(yōu)化了代碼錯誤搜索過程。
顯然,本領(lǐng)域的技術(shù)人員應(yīng)該理解,上述的本發(fā)明的各模塊或各步驟可以用通用的計(jì)算系統(tǒng)來實(shí)現(xiàn),它們可以集中在單個的計(jì)算系統(tǒng)上,或者分布在多個計(jì)算系統(tǒng)所組成的網(wǎng)絡(luò)上,可選地,它們可以用計(jì)算系統(tǒng)可執(zhí)行的程序代碼來實(shí)現(xiàn),從而,可以將它們存儲在存儲系統(tǒng)中由計(jì)算系統(tǒng)來執(zhí)行。這樣,本發(fā)明不限制于任何特定的硬件和軟件結(jié)合。
應(yīng)當(dāng)理解的是,本發(fā)明的上述具體實(shí)施方式僅僅用于示例性說明或解釋本發(fā)明的原理,而不構(gòu)成對本發(fā)明的限制。因此,在不偏離本發(fā)明的精神和范圍的情況下所做的任何修改、等同替換、改進(jìn)等,均應(yīng)包含在本發(fā)明的保護(hù)范圍之內(nèi)。此外,本發(fā)明所附權(quán)利要求旨在涵蓋落入所附權(quán)利要求范圍和邊界、或者這種范圍和邊界的等同形式內(nèi)的全部變化和修改例。