日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

【开发者成长】阿里代码缺陷检测探索与实践

發(fā)布時間:2024/8/23 46 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【开发者成长】阿里代码缺陷检测探索与实践 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

目前PRECFIX技術(shù)已經(jīng)在阿里巴巴集團(tuán)內(nèi)部落地并獲得好評;關(guān)于“PRECFIX”技術(shù)的論文被國際軟件工程大會(ICSE)收錄。

張昕東(別象) 阿里巴巴 云研發(fā)事業(yè)部 算法工程師

?

【以下為別象分享實錄】

阿里巴巴在缺陷檢測技術(shù)方面遇到的三個挑戰(zhàn)

編碼是DevOps的重要一環(huán),我所在的部門主要負(fù)責(zé)阿里巴巴集團(tuán)的代碼托管。在平臺業(yè)務(wù)的背后,我們建設(shè)了一系列智能化能力用來賦能前線業(yè)務(wù)。依賴底層的代碼圖譜和離線數(shù)倉(離線數(shù)據(jù)倉庫)的數(shù)據(jù)能力,代碼智能衍生出了缺陷檢測、代碼生成、代碼克隆、代碼安全等能力。今天主要介紹一下我們在缺陷檢測領(lǐng)域的初步探索和實踐。

缺陷檢測和補丁推薦幾十年來一直是軟件工程領(lǐng)域的難題,又是研究者和一線開發(fā)者最為關(guān)心的問題之一。這里講的缺陷不是網(wǎng)絡(luò)漏洞、系統(tǒng)缺陷,而是隱藏在代碼中的缺陷,也就是程序員們戲稱的“八阿哥”(即BUG)。每位開發(fā)者都希望有一種智能的缺陷檢測技術(shù)來提升代碼質(zhì)量,避免踩坑。所謂“最迷人的最危險”,如此令人著迷的技術(shù)自然有著重重阻礙。

在研究了現(xiàn)有的一些解決方法以及阿里巴巴內(nèi)部數(shù)據(jù)集的特征后,我們將缺陷檢測技術(shù)在阿里巴巴產(chǎn)品落地上的挑戰(zhàn)歸納為三個方面:

復(fù)雜的業(yè)務(wù)環(huán)境
首先阿里巴巴經(jīng)濟體業(yè)務(wù)種類繁多,有底層系統(tǒng)中間件的代碼,有物流的代碼,也有安全、人工智能等各個領(lǐng)域的代碼,業(yè)務(wù)在變,代碼缺陷類型也在變。代碼數(shù)據(jù)只增不減,代碼缺陷類型捉摸不透,缺陷檢測的困難不言自明。

以Java語言為例,學(xué)術(shù)界的Java缺陷公開數(shù)據(jù)集常用的是Defect4J。Defect4J包含6個代碼庫,有將近400個人工確認(rèn)的缺陷和補丁。這些代碼庫是比較基礎(chǔ)常規(guī)的代碼庫,缺陷種類容易劃分,一部分研究者也做了特定缺陷種類的研究,對癥下藥效果尚可,然而換了一種缺陷類型,那么檢測的效果就很難令人滿意了。

在阿里巴巴數(shù)據(jù)集中,有眾多的缺陷類型難以定義,希望能有一種對缺陷類型泛化能力強的缺陷檢測與補丁推薦的方法,不說“包治百病藥到病除”,但希望能夠適應(yīng)不同的“病癥”,提高代碼“免疫力”。

有限的輔助資源
第二大挑戰(zhàn)來源于有限的輔助資源,這也是導(dǎo)致許多學(xué)術(shù)界相關(guān)成果無法直接復(fù)現(xiàn)利用的原因。

何謂輔助資源,常用者有三:測試用例,缺陷報告,缺陷標(biāo)簽。

雖然大多數(shù)線上代碼都已經(jīng)達(dá)到了很高的測試覆蓋率,但是由于代碼質(zhì)量參差,有一大部分代碼庫是缺乏測試用例的,我們也缺少足夠的缺陷報告去直接定位缺陷。我們也想嘗試過通過缺陷標(biāo)簽來學(xué)習(xí)缺陷模式,然而自動打標(biāo)簽的方法準(zhǔn)確率不高,而人工給如此龐大的數(shù)據(jù)集打標(biāo)簽是不太現(xiàn)實的。

產(chǎn)品落地的要求

而最難現(xiàn)實的是第三大挑戰(zhàn),來自產(chǎn)品的落地要求。

作為一項技術(shù),需要在產(chǎn)品中尋找落地的機會。而真實的落地又對技術(shù)有極高的要求:我們構(gòu)想的主要落地場景是代碼評審中的缺陷靜態(tài)掃描及補丁推薦。產(chǎn)品經(jīng)理說:“檢測過程要高效,盡量不要給誤報,定位缺陷還不夠,補丁方案還得讓用戶知道。”

業(yè)界和學(xué)術(shù)界較為流行的缺陷檢測手段和其局限性

搞研究做創(chuàng)新自然不能固步自封,閉門造車。我先來給大家簡單地介紹一些相關(guān)領(lǐng)域的一些現(xiàn)有成果。

主要從缺陷檢測,補丁推薦,以及其他相關(guān)的技術(shù)應(yīng)用三個方面做介紹。

缺陷定位技術(shù)
關(guān)于缺陷定位技術(shù)的這些歸納總結(jié)主要來自于熊英飛老師(北京大學(xué)新體制副教授)的論文。主要方法大類有:基于光譜的缺陷定位,基于突變的缺陷定位,堆棧分析等等。

比如基于光譜的缺陷定位是基于測試用例,通過的測試用例經(jīng)過的代碼行給予正向分?jǐn)?shù),失敗的測試用例經(jīng)過的代碼路徑給予負(fù)面分?jǐn)?shù),類似于光譜的形式將分?jǐn)?shù)較低的一些代碼行歸類為潛在缺陷行。

這些缺陷定位手段大多關(guān)注特定缺陷,在定位某些特定缺陷時準(zhǔn)確率明顯高于其它缺陷,比如Predicate Switching主要用于檢測條件語句中的bug。
第二個局限在于誤報率較高,以Defect4J數(shù)據(jù)集測試結(jié)果為例,以上方法中準(zhǔn)確率最高的是基于光譜的定位,但是TOP1的命中率也只有37%左右。有研究工作將這些各有所長的缺陷定位手段整合起來一起判斷,但誤報率仍然高于50%。
最重要的一點是,上述的缺陷定位手段不提供補丁信息,這一點在實際應(yīng)用過程中是很致命的,比如基于光譜的定位會返回多個潛在缺陷行,但是沒有明確的修復(fù)方案,用戶會比較迷茫。

補丁推薦技術(shù)

關(guān)于補丁推薦技術(shù),比較具有代表性的研究是Generate-and-validate approach,這種類型下的研究成果大體思路是基于失敗的測試用例,定位到代碼上下文,然后通過隨機替換代碼元素,或基于語義不斷嘗試改變抽象語法樹上的結(jié)點,并利用測試用例或其它可驗證信息去驗證修改的結(jié)果,直到測試用例或其他驗證手段跑通。

這些補丁生成的方法主要有三大局限,首先是準(zhǔn)確率低,主要體現(xiàn)在Overfitting(過度擬合)問題上,意思是生成的修復(fù)片段和現(xiàn)實中工程師實際的修復(fù)方式不同,有些修復(fù)甚至是面向測試用例的修復(fù)而不是面向真實缺陷的修復(fù)。左圖是某論文中一個Overfitting的例子,“Generate-and-validate”方法將if條件修改為了一個無意義的恒等于true的條件,使得該方法每次安全地return,這樣的修改確實能跑通測試用例,但是對真實的bug是無濟于事的。

第二個明顯的局限是耗時長,消耗的計算資源較多,這種修復(fù)方法往往是小時級的,而且他是基于編譯的,需要不斷地測試運行,效率較低。

此外,這種方法對測試用例完備性的要求非常高,它既考驗測試的覆蓋率,又考驗了測試用例設(shè)計的合理性。

其它應(yīng)用技術(shù)
還有一些缺陷檢測或補丁推薦技術(shù),可能大家有所耳聞,特別是Facebook和Google的,我也簡單地介紹下。

? Simfix和CBCD主要是基于缺陷報告的補丁生成,利用代碼克隆把缺陷報告和補丁遷移到新代碼上。
? Ubisoft的CLEVER首先基于特征做了commit級別的缺陷預(yù)測,對風(fēng)險較大的一些commit做二次檢測,二次檢測的方法是將缺陷報告根據(jù)代碼的dependency聚類起來,然后做抽象語法樹的節(jié)點相似度比較,游戲代碼往往有一些相似的缺陷。
? Bugram是將代碼解析成token序列,利用Ngram算法來預(yù)測出現(xiàn)某一個token的概率,概率低的token可能是個缺陷點,這種方法當(dāng)代碼復(fù)雜度變高或代碼詞匯數(shù)量過大后,效果就急劇下降。
? Infer,Getafix,Sapfix都是Facebook提出的,做的都很不錯。Sapfix主要是針對移動手機的UI做類似Fuzzing的缺陷檢測,Infer主要針對代碼的NPE問題做了偏規(guī)則的檢查,所以準(zhǔn)確率較高,Getafix是在Infer的檢測結(jié)果的基礎(chǔ)之上,對工程師修復(fù)的補丁做了模式聚類,將常用的NPE修復(fù)模式統(tǒng)計生成出來。
? Tricorder和Findbugs等工具都是比較成熟的代碼檢測器,開發(fā)者可以基于這之上定制自己的檢測機制,但比較依賴規(guī)則的人工制定。

我們?yōu)槭裁刺岢鯬RECFIX方法

經(jīng)過調(diào)研后,我們發(fā)現(xiàn)外部的已有技術(shù)方法不能完全解決阿里巴巴面臨的挑戰(zhàn)和問題,于是我們提出了PRECFIX方法(Patch Recommendation by Empirically Clustering)。

我們首先在阿里巴巴數(shù)據(jù)集中復(fù)現(xiàn)了一個基于特征工程的commit(代碼提交)級別缺陷風(fēng)險檢測,這個在之前講Ubisoft的Clever的時候有提過,具體方法是從代碼數(shù)據(jù)集中根據(jù)托管系統(tǒng)Git建立commit父子關(guān)系圖,利用改進(jìn)的SZZ方法對commit進(jìn)行自動打標(biāo)簽,然后抽取出一部分特征如下所示,然后利用Xgboost 或者隨機森林(Random Forest)對特征和標(biāo)簽進(jìn)行訓(xùn)練,將模型用于commit風(fēng)險的檢測。特征主要分為規(guī)模、代碼分布、目的、開發(fā)者經(jīng)驗以及文件修改五大維度,共14個子特征。

以SZZ算法作為標(biāo)簽數(shù)據(jù)的模型在準(zhǔn)確率上有瓶頸。SZZ算法雖然邏輯合理,在公開數(shù)據(jù)集上有比較好的表現(xiàn),然而在我們的代碼數(shù)據(jù)集上,準(zhǔn)確率不高,人工觀察了數(shù)百條SZZ算法標(biāo)注的缺陷commit,其中僅有53%是真實的修復(fù)行為。“噪聲點”主要來自以下幾種場景:業(yè)務(wù)型的修復(fù)與代碼無關(guān),注解日志的改動,測試類的調(diào)整,代碼風(fēng)格的優(yōu)化,代碼改動本身是用于“debug”的所以message中帶有“debug”信息等等。而更進(jìn)一步,僅有37%的修復(fù)型代碼改動可以遷移到新的代碼上,這也就意味著有些代碼改動雖然是真實的修復(fù),但是由于改動量過于復(fù)雜,或者只與特定環(huán)境,特定上下文相關(guān),沒有可借鑒的價值。

通過對標(biāo)簽數(shù)據(jù)的細(xì)致分析,我們認(rèn)為自動化的標(biāo)簽不滿足我們的需求,而且打缺陷標(biāo)簽對打標(biāo)者的技術(shù)要求較高,對海量的代碼改動歷史打標(biāo)簽也是不現(xiàn)實的。

我們開始不盲目尋找和復(fù)現(xiàn)方法,而是用心去感受和發(fā)現(xiàn)開發(fā)者在日常開發(fā)過程中的修復(fù)行為,我們總結(jié)了以下幾點:首先,借鑒于SZZ算法,commit message中往往包含了用戶的修復(fù)意圖,可以依據(jù)commit message來過濾出一部分?jǐn)?shù)據(jù)。另外我們在調(diào)研SZZ算法數(shù)據(jù)時,發(fā)現(xiàn)75%的修復(fù)提交都有這樣的模式:刪除一些缺陷代碼,然后新增一些代碼,比如修改了一個參數(shù),在diff(差異文件)中便是刪除了一行,新增了一行。

還觀察到一個細(xì)節(jié)就是一個修復(fù)的操作往往涉及的文件數(shù)不超過兩個,而一些不太規(guī)范的commit里面含有大量的文件,即使里面包含了修復(fù)行為,也會被稀釋掉,引入不被歡迎的噪音。

同時我們也調(diào)研了在代碼評審階段用戶比較關(guān)心的缺陷,如故障點、重構(gòu)點、代碼風(fēng)格、性能問題等等,很多問題都有重復(fù)出現(xiàn)、重復(fù)修改的記錄。我們萌生了從海量的提交歷史中挖掘出重復(fù)常見的缺陷,防止開發(fā)者再次犯錯的想法。

于是我們提出了PRECFIX,Patch Recommendation by Empirically Clustering,也是這次ICSE收錄的論文中描述的方法,后期會在云效產(chǎn)品中使用。其實思路方法比較直接簡潔,主要分為三步,首先從代碼提交數(shù)據(jù)中提取“缺陷修復(fù)對”,然后將相似的“缺陷修復(fù)對”聚類,最后對聚類結(jié)果進(jìn)行模板提取,這個缺陷檢測和補丁推薦技術(shù)可以用于代碼評審,全庫離線掃描等等。用戶的反饋以及我們?nèi)斯さ膶彶榭梢赃M(jìn)一步提高模型推薦質(zhì)量。

實現(xiàn)PRECFIX方法的技術(shù)細(xì)節(jié)

接下來我們聊一下實現(xiàn)PRECFIX方法的技術(shù)細(xì)節(jié)。首先是“缺陷修復(fù)對提取”。有朋友可能會有疑問,何為“缺陷修復(fù)對”?“缺陷修復(fù)對”如何提取?

缺陷修復(fù)對提取

這得先從幾個數(shù)字講起。SZZ算法利用Blame信息去追溯引入缺陷的commit以及缺陷行,我們觀察發(fā)現(xiàn),有25%的文件的缺陷行源自多個文件,這就意味著利用blame信息去溯源可能會將一個缺陷追溯到兩個源頭,而將一個缺陷的代碼行一分為二很有可能是沒有意義的。

通過blame信息去追溯缺陷代碼行不夠準(zhǔn)確,而我們想要的缺陷相關(guān)的代碼上下文實際上就是這次修復(fù)型commit提交前該文件最后一次提交的內(nèi)容,我們可以直接通過本次提交的文件和對應(yīng)的diff還原出本次提交前的文件內(nèi)容。

我們發(fā)現(xiàn),大多數(shù)的修復(fù)行為是以方法為單位的,所以我們提出了以方法為單位的“缺陷修復(fù)對”提取方法,即將方法體內(nèi)的diff chunks(差異文件區(qū)塊)合并,生成一個缺陷修復(fù)對。當(dāng)然也可以不以方法體為范圍,直接以diff chunk為單位去提取缺陷修復(fù)對,這些都各有利弊,如果以diff chunk為單位去提取,那就不需要源代碼信息了,直接解析diff即可。

在提取過程中有個小tips就是將缺陷片段和修復(fù)片段歸一化,比如將空格和換行符去掉,然后比較兩者,將相同的缺陷修復(fù)對過濾掉,這樣能過濾掉一部分代碼格式修改。

我們發(fā)現(xiàn)60%的commit僅包含了1-2個文件,但也存在小部分的不規(guī)范commit包含了數(shù)十個甚至上百個文件。如之前所說,我們認(rèn)為一次修復(fù)行為關(guān)聯(lián)的文件往往在三個以下,為了減小噪聲的引入,在提取缺陷修復(fù)對的過程中建立過濾機制。其實這個commit文件數(shù)量的限制是準(zhǔn)確率和召回率的權(quán)衡,在真實實踐中我們?yōu)榱苏倩芈事晕⒎艑捔讼拗?#xff0c;將閾值設(shè)為了5。

通過SZZ算法標(biāo)注的代碼缺陷47%不夠準(zhǔn)確。我們沿用了SZZ的利用commit message的數(shù)據(jù)采集步驟,所以這個缺陷修復(fù)對的提取過程還是會存在大量的噪聲難以去除。我們想到了聚類,將常見的缺陷與補丁聚類起來,總結(jié)成模板,一些噪聲或沒有借鑒意義的缺陷修復(fù)會被自然地過濾。

缺陷修復(fù)對聚類

提取完缺陷修復(fù)對后,為了盡量減少噪音,并且我們的目的是提取共性缺陷修復(fù)記錄,于是采用了聚類的方法,將相似的缺陷修復(fù)對聚類在一起,得到一些共性的缺陷。

由于事前無法預(yù)測類簇數(shù)量,我們沒有使用Kmeans聚類算法,采用了目前比較成熟的基于密度的DBSCAN算法,當(dāng)然也可以使用pairwise的比較和合并,也就是所有情況都比一遍。

聚類方式上,我們嘗試過很多種,有單獨聚類缺陷片段的,效果不錯,但是修復(fù)片段的分析成為了難點,因為同樣一段缺陷片段有不同的修復(fù)方案,很難自動化地分析。我們最后嘗試了同時聚類缺陷和修復(fù)片段,這樣聚類的方式可以在匹配上缺陷片段時直接給出修復(fù)片段,不用再另外考慮如何做修復(fù)推薦。

直接使用DBSCAN效率較低,以我們的實驗數(shù)據(jù)量來講,大概需要70個小時。于是,我們在DBSCAN的基礎(chǔ)上做了一定的優(yōu)化,主要有圖表上的幾種方式。我們基于MapReduce實現(xiàn)聚類,Mapper階段做缺陷修復(fù)對的預(yù)處理,Reducer階段跑DBSCAN。第一種優(yōu)化方式是在Mapper階段采用KDTree或者SimHash算法將比較相近的缺陷修復(fù)對分發(fā)到一個Reducer中做并行聚類,時間性能大概提升了4倍。類簇?fù)p失率主要是和基礎(chǔ)版的DBSCAN算法相比,大概損失了6%。

大多數(shù)的缺陷修復(fù)對互相之間是沒有任何關(guān)聯(lián)的,而我們利用代碼克隆技術(shù)比較兩個片段又是最耗時的部分,圖上的APISEQ便是我們優(yōu)化“不必要比較”的方法。我們洞察了這批缺陷修復(fù)對數(shù)據(jù)集,發(fā)現(xiàn)幾乎所有的片段都或多或少包含了方法調(diào)用,沒有方法調(diào)用的片段大概率是一些無意義的噪聲,所以我們可以在聚類比較的過程中先比較兩個片段是否含有相同的API,如果有的話再進(jìn)行比較,通過這個方法時間性能又提高了四倍。

我們也嘗試了比較新穎的并行DBSCAN算法,速度非常快,但是類簇?fù)p失相對較大。這個數(shù)據(jù)處理的過程是定期的離線計算,頻率較低。最終權(quán)衡之下,我們選擇了耗時相對較短,損失率較小的KDTree或APISEQ+KDTREE的聚類方法。

至于聚類過程中的兩個片段的代碼克隆比較方式,我們發(fā)現(xiàn)兩種互補的計算方式的結(jié)果明顯優(yōu)于單個計算方式,我們的最佳實踐是“編輯距離”和“Jaccard”的加權(quán)平均,因為“編輯距離”能夠捕捉到token(代碼元素)的順序關(guān)系,而Jaccard能計算token重合比例。

模版提取與匹配

最后是“模版提取”:為了提升用戶體驗,我們希望將同一類簇的片段聚合起來提取出模板,降低用戶的理解成本。

如上圖所示,同一類簇的兩個片段非常相似,我們先遞歸地使用最長子序列算法,黃色部分為匹配的內(nèi)容。一些不匹配的內(nèi)容除了左邊的片段多了一句以外,其他部分實際上是變量名不同,我們將不同的變量名分析提取出來,存儲為“@Para”的格式方便后期匹配。

當(dāng)掃描到新的缺陷片段時,我們基于模板識別出它的變量名,并直接用新的變量名替換補丁模板中的“@Para”參數(shù),然后自動推薦出帶有新參數(shù)的修復(fù)建議。

下面來看幾個PRECFIX聚類得到的模板。第一大類是“合理性檢查”,修復(fù)片段做了長度的判斷,合理性檢查也包括了空值檢查。

第二個類是“API變更”, API的參數(shù)發(fā)生了改變,增加了Gpu id,第一個參數(shù)的來源也做了修改。API變更還包括了方法名的改動,參數(shù)的增刪改,這是非常常見的類型。

還有一個大類是做查看聚類結(jié)果之前沒想到的,就是“API封裝”,工程師往往會把功能獨立,經(jīng)常復(fù)用的代碼段封裝起來,減少代碼重復(fù)度和維護(hù)成本,而且工具類會將方法寫的比較完善,減少開發(fā)者在編寫時產(chǎn)生的不必要的失誤。

當(dāng)然Precfix也不是代碼缺陷的特效藥,只是提供了一種從代碼庫中挖掘缺陷的思路。模板數(shù)量和誤報率需要持續(xù)地跟進(jìn)和維護(hù)。

PRECFIX方法已經(jīng)在阿里巴巴集團(tuán)內(nèi)部落地,在內(nèi)部公開庫中掃描出了800多種缺陷類型,3萬多個缺陷,并將結(jié)果對用戶進(jìn)行了訪談,獲得了普遍的好評。后續(xù),該方法也會在“云效”產(chǎn)品中應(yīng)用,供更多開發(fā)者使用。

以上內(nèi)容來自別象在“云效開發(fā)者交流群”中的視頻直播課程,您可以釘釘搜索群號(23362009)入群,收看視頻回放。

關(guān)于云效:
云效,企業(yè)級一站式DevOps平臺,源于阿里巴巴先進(jìn)的管理理念和工程實踐,致力于成為數(shù)字企業(yè)的研發(fā)效能引擎!云效提供從“需求 ->開發(fā)->測試->發(fā)布->運維->運營”端到端的在線協(xié)同服務(wù)和研發(fā)工具,通過人工智能、云原生技術(shù)的應(yīng)用助力開發(fā)者提升研發(fā)效能,持續(xù)交付有效價值。

原文鏈接
本文為云棲社區(qū)原創(chuàng)內(nèi)容,未經(jīng)允許不得轉(zhuǎn)載。

總結(jié)

以上是生活随笔為你收集整理的【开发者成长】阿里代码缺陷检测探索与实践的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。