大模型在程式碼缺陷檢測領域的應用實踐

人工智慧洞察站發表於2023-11-06

  靜態程式碼掃描(SA)能快速識別程式碼缺陷,如空指標訪問、陣列越界等,以較高ROI保障質量及提升交付效率。當前掃描能力主要依賴人工經驗生成規則,泛化能力弱且迭代滯後,導致漏出。

  本文提出基於程式碼知識圖譜解決給機器學什麼的問題,以及基於程式碼大模型解決機器怎麼學的問題,讓計算機像人一樣看懂程式碼,並自動發現程式碼中的缺陷,給出提示,以期達到更小的人力成本,更好的效果泛化和更高的問題召回。

   01 程式碼缺陷檢測背景介紹

  靜態程式碼掃描(SA)指在軟體工程中,程式設計師寫好原始碼後,在不執行計算機程式的條件下,對程式進行分析檢查。透過在程式碼測試之前,在編碼階段就介入SA,提前發現並修復程式碼問題,有效減少測試時間,提高研發效率,發現BUG越晚,修復的成本越大。  

  MEG的SA能力於2018年建立,支援C++、GO等語言,建設100+個規則,覆蓋大部分MEG的模組,一定程度保障線上質量。當前檢測主要依賴人工生成規則,存在人工編寫成本高,以及泛化能力弱且迭代滯後,導致問題漏出。2022年Q2,我們團隊嘗試引入大模型:透過程式碼語言大模型,實現機器自主檢測缺陷,提升泛化能力和迭代效率,減少人工編寫規則的成本。接下來,為大家帶來相關介紹。

   02 基於規則的程式碼缺陷檢測主要問題

  隨著缺陷規則增多,覆蓋的語言和模組增多,有兩個突出的痛點急需解決:

  1、每種規則都需人工根據經驗和後續的漏出分析維護,成本較高;以空指標場景為例,人工編寫的規則程式碼共4439行,維護的迴歸case共227個,但Q2仍有3個bug漏出。我們如何引入大模型減少開發成本,提質增效?

  2、有效率偏低,掃描的能力有限(如斷鏈、框架保證非空、複雜場景靜態很難識別等,且風險的接受不同,掃描的部分高風險問題存在修復意願低,對使用者造成打擾。我們如何透過模型,從歷史誤報中學習經驗,進行過濾,減少打擾,提升召回?

   03 解決方案

  為了解決2個痛點問題,提出對應的解決方案。

  3.1 基於大模型的缺陷自動掃描

  如何讓計算機像人一樣看懂程式碼,並自動發現程式碼中的缺陷,給出提示。要讓計算機自主進行缺陷檢測,核心需要解決2個技術難題:

  【學什麼】給計算機輸入什麼內容,能讓計算機更快、更好的學習;主要依託程式碼知識圖譜提取目標變數相關的片段,減少機器學習需要的樣本量,提升學習的準確性。

  【怎麼學】針對輸入的內容,採用什麼演算法,能讓機器像人一樣讀懂多種程式語言,並完成檢測任務;採用深度學習的方法,主要包含預訓練和微調兩部分。預訓練技術讓計算機在海量無標籤的樣本中學習到多種語言的通用程式碼語義,本專案主要採用開源的預訓練大模型。微調技術透過給大模型輸入缺陷檢測的樣本,從而得到適配場景的大模型,讓機器自主的進行缺陷識別。  

  3.1.1 程式碼知識圖譜提取片段

  為了平衡模型效能和資源,不同大模型允許輸入的token量級不同,如Bert模型限制512個token,因此,需要對輸入進行縮減。程式碼知識圖譜是基於程式分析手段,對業務原始碼經過模糊或精準的詞法分析、語法分析和語義分析後,結合依賴分析、關係挖掘等手段,構建得到的軟體白盒程式碼知識網。圖譜提供了多種資料訪問方式,使用者可以低成本的訪問程式碼資料。

  藉助於程式碼知識圖譜能力,可以根據不同場景制定不同的與目標變數或目標場景相關的上下文原始碼獲取能力,提取的關鍵步驟包括:

  構建被分析程式碼的知識圖譜

  目標變數檢測識別:在變更程式碼中識別目標變數,作為待檢測變數

  變數依賴分析:基於控制流和資料流的與目標變數相關的依賴變數分析

  特徵語句提取和剪枝  

  以空指標風險檢測為例,最終得到如下樣例的程式碼切片資訊:  

  3.1.2 採用大模型學習演算法進行缺陷預測

  大模型檢測缺陷有兩種思路:

  1、一種是透過判別式的方法,識別是否有缺陷以及缺陷型別;

  2、一種是透過生成式的方法,構建prompt,讓程式自動掃描所有相關缺陷。

  本專案主要採用判別式的方法,並在實踐中證明該方法具有一定可行性。生成式的方法同步實驗中,接下來分別介紹兩種思路的一些實踐。

  3.1.2.1 判別式的方法

  透過分類的思想,基於模型,從歷史的樣本中學習規律,從而預測新樣本的類別。深度學習眾多演算法中,如TextCNN、LSTM等,應該採用哪一種?我們透過多組對比實驗,最終選擇效果更優的BERT程式碼大模型。  

△模型效果

  採用BERT進行缺陷檢測共含3步,分別是預訓練、微調和推理。

  預訓練階段採用開源的多語言大模型,已較好的學習多種程式語言的語義。

  微調階段,給模型輸入上述透過程式碼知識圖譜提取的變數使用點相關的切片,以及是否有缺陷或者缺陷型別的標籤,生成微調模型,讓機器具備做檢測任務的能力。輸入的格式:

  { "slices": [{"line":"行程式碼內容", "loc": "行號"}], "mark": {"label":"樣本標籤", "module_name":"程式碼庫名", "commit_id":"程式碼版本", "file_path":"檔名", "risk_happend_line":"發生異常的行"} }

  推理階段,分析使用點目標變數的相關切片,透過微調模型進行預測,得到使用點是否有缺陷,以及缺陷型別

  模型上線後,使用者對結果反饋狀態包括誤報和接受,採集真實反饋樣本,加入微調模型自動訓練,從而到達自動迭代、快速學習新知識的目的。  

  3.1.2.2 生成式的方法

  生成式模型百花齊發,有閉源的如chatgpt、文心一言,有開源的如llama、bloom和starcode等。我們主要嘗試文心一言、llama和bloom,透過prompt(few shot、引入思維鏈、指定抽象的引導規則)和微調的方式,探索模型在空指標缺陷檢測的預測效果。整體f1測度不高,更優的bloom61.69%,相比Bert路線的80%有差距,且模型的穩定性較差。因生成式路線有自身的優勢,如引數量大存在智慧湧現具有更強的推理能力,允許輸入的token量不斷增加可減少對切片清洗的依賴,可與修復一起結合等,我們預判在缺陷檢測場景生成式是個趨勢,接下來我們將繼續最佳化,不斷嘗試prompt和微調,透過更合適的引導,更好的激發模型的潛力,從而提升生成式方法在檢測場景的效果。  

  3.2 採用規則+機器學習進行誤報過濾

  缺陷檢測場景識別的缺陷是風險,存在接受度問題,如何過濾掉其中低風險問題,是個難題。透過分析誤報和修復的樣本,我們採集誤報相關的特徵,如指標型別,模組誤報率、檔案誤報率等跟誤報相關的10+特徵,訓練機器學習模型(邏輯迴歸),判斷是否需要過濾.

  整體方案架構圖如下:  

   04 業務落地

  基於AI的程式碼缺陷檢測能力可以整合進入code管理平臺,每次程式碼提交,展示可能存在的程式碼缺陷,阻塞合入,並採集研發人員的反饋,便於模型迭代。

   05 收益和展望

  5.1 收益

  透過理論和實踐證明,讓計算機自主學習程式語言並完成缺陷檢測任務具有一定可行性。

  1、本專案的方法已在IEEE AITest Conference 2023發表論文:

  《Leveraging Deep Learning Models for Cross-function Null Pointer Risks Detection》()。

  2、實際落地效果:2023Q2 C++空指標場景已覆蓋1100+模組,修復問題數662個,相比規則型靜態程式碼掃描召回佔比26.9%,增量召回484個,重合度26.8%,初步證明AI的召回能力,開啟了大模型做程式碼缺陷檢測的大門,同時也驗證大模型具備傳統規則的擴召回、低成本的優勢,可形成標記+訓練+檢測的自閉環。

  5.2 展望

  基於5.1收益,給了我們用大模型做程式碼缺陷檢測的信心,後續我們繼續在以下幾個方面加強:

  1、擴充套件更多語言和場景,如除零、死迴圈、陣列越界場景,並在多語言go、java等進行快速訓練,並進行釋出;

  2、隨著生成式模型的興起,也會逐漸積累有效的問題和修復資料,貢獻文心通用大模型,進行預訓練和微調,以探索生成式模型在智慧缺陷檢測與修復領域的應用;

  3、同時將調研更多基礎切片技術,拿到更多豐富有效程式碼切片,以提升準召率。

來自 “ 百度Geek說 ”, 原文作者:百度Geek說;原文連結:https://server.it168.com/a2023/1102/6827/000006827707.shtml,如有侵權,請聯絡管理員刪除。

相關文章