標籤:

如何看待能自動修復bug的CodePhage?

麻省理工發明了神器 CodePhage,讓程序自己修復 BUG。CodePhage 能夠在沒有獲取訪問源代碼許可權的前提下尋找適合的代碼,然後以相同的前提對 BUG 程序進行不斷的調試,直至找到最理想的修復代碼為止。

相關報道:MIT又有黑科技 任何程序都能自動修復BUG_系統工具_cnBeta.COM


各位開噴的同學,拜託起碼先看看文檔,了解一下這個東西到底能做什麼再噴嘛。

每一個項目都有自己的scope,以及goal和none-goal。前面有同學說的bug/feature之爭,我不認為會是這個項目的goal。從一個該項目簡介的slides上看,它的goal很窄,只是

  1. Finding and eliminating defects

  2. Transferring code between applications

這裡有一篇CodePhage的簡介(http://www.srl.inf.ethz.ch/workshop2014/eth-rinard.pdf),裡面舉了個例子:

有兩個應用,一個是ImageMagick Display, 一個是ViewNior, 都是圖片瀏覽應用。在打開一個有問題的圖片(cat.tif)時Display直接崩潰,而ViewNior則檢測出圖片問題並給出一個錯誤提示。要做的事情就是定位是什麼導致了ViewNior給出錯誤提示而Display直接崩潰,然後找出ViewNior用於檢測這個錯誤的代碼並將代碼應用到Display上去修復這個問題。這裡ViewNior成為了Donor(捐獻者)而Display則成為了Recipient(受體)。

找出donor的錯誤檢測代碼並應用到recipient上去,說起來簡單,實現起來可是困難重重,需要判斷輸入的哪一部分觸發了程序的哪個if/else分支,最終引發了錯誤提示,這個輸入數據與代碼分支的組合數量就很恐怖了。另外就算找到了donor上二進位的分支,如何找到對應的donor源代碼,且將donor源代碼映射到recipient正確的源代碼位置,都需要做很多工作的。我不是專業人員,裡面提到的很多技術也不懂,有興趣的同學自己去看原文。

===== 分割線 =====

  1. 保持一顆敬畏之心,不要對不了解的東西隨便發表意見。

  2. slides我只是簡單看了一眼,有說的不對的地方歡迎指正。


一直在關注MIT的另外一個組的自動bug修復的研究,CodePhage這篇文章一個多月前就在MIT的技術報告上看到了,但一直來得及讀,沒想到現在媒體反響這麼大,可能是文章6月份投到PLDI 15上的緣故。

老闆去年就叫我看Bug自動修復方面的內容,現在前前後後也看了一些文章(可惜自己還沒有什麼思路),可能這些應該寫在我的畢業論文里,現在先寫點出來,大家討論討論吧。。。

舊我目前看到的文獻來看,所謂的自動bug修復還很不成熟,只是一些人在很強的約束條件下做過一點實驗(我感覺Code Phage也不例外),能夠修復一些簡單的bug,但是可能效果還不是很好。下面先從題主提到的Code Phage講起:

Code Phage

這篇文章的思路很新穎,但是我感覺最重要的還是作者強大的系統實現能力。

該方法的過程如下圖:

圖片來源:Code Phage的原始文章

主要想法就是,給定一個有bug的程序(recipient),想要在其它程序(donor)中找到該bug的補丁,並把它移植過來。首先,從bug程序中提取兩個test case,一個是可以pass,另一個則是fail的。然後就去已經建好的code資料庫里搜索能夠同時pass兩個test case(當然,大前提是input的格式一樣)的程序(Donor Selection)。

然後就是各種黑科技,在binary code的層面上,分別記錄兩個test case的執行路徑,如果在某個branch處二者分道揚鑣了,就說明這個地方很有可能是patch所在(該branch處的code稱之為candidate check,這一步叫做Candidate Check Discovery)。

下一步要把那個candidate check 改寫成 application-independent symbolic expression,用來描述輸入的byte是怎樣的處理邏輯(我的理解是將那一小段binary code反編譯成某個中間語言),這樣patch就準備好了(Check Excision)。

接著要把patch應用到待修復的程序中去,首先要找到patch的插入點(Check Insertion),然後收集上下文的變數或者表達式等嘗試代入到application-independent symbolic expression裡面去(Check Translation),然後不斷verify bug是否消除(Patch Validation)。

Code Phage的思路很清晰,但是實現過程很困難,從binary code的層面上進行分析我是不敢想(不得不膜拜MIT的水平)。

但同時,我感覺Code Phage的局限性還是很大的(畢竟bug修復對程序員來說就是一件很麻煩的事情),引用他的同門的一句話:"Code Phage relies on the existence of a specific donor application that contains the exact program logic to fix an error",構建donor DB就是一個很繁雜的事情,任意給個bug程序,怎麼能恰好找到donor呢?

當然,作者的假設就是某個bug程序的補丁,可以在其它程序里找到。下面就來簡要說一說幾年前一個類似的假設:某個bug程序的補丁,可以在bug程序自身找到。這就是前些年炒得比較火的GenProg。

GenProg

這個最早是Virginia 大學的Weimer 等人提出來的(與Code Phage不同,這是基於源代碼的修復),採樣遺傳演算法進行bug修復(遺傳演算法真是萬能的。。。)。他們把程序看成statement的集合,程序的修復只到statement的粒度。然後對應到遺傳演算法的術語中,他們將個體看成insert某個statement(來自上下文), delete某個statement, replace某個statement(來自上下文)的操作序列,然後不斷地經過mutation和crossover的進化(fitness的衡量是pass test case的個數),最終期望能夠將bug修復。作者insert以及replace的目的就是想在程序上下文找到修復bug的方案。

這個方法在2009年提出,一直到2012年,只改進了一些小的細節,但水的文章可不少。2012年甚至獲得best paper(這篇文章中指出,他們選取了105個大型程序,發現已經能夠修復其中的55個!),作者之一Claire Le Goues也甚至因這些工作在CMU找到了教職。2013年Claire Le Goues發了篇綜述文章,寫了目前bug自動修復過程中存在的挑戰,從此這個小組就沒有怎麼更新工作了。

PAR

可是到了2013年,港科大的一個叫Kim的人在ICSE上提出了PAR的bug自動修復方法。他的思路是:先從包含人工patch的大型程序資料庫中挖掘出最常見的錯誤,建立相應的修復模板,然後匹配已有的修復模板進行修復。作者稱自己的方法超越了GenProg,但幾年來從未公布自己的代碼和實驗程序。

SemFix與NOPOL

2013年的ICSE上,NUS提出了SemFix,將問題縮小到修復賦值語句bug和if條件語句bug,使用test case與Symbolic Execution得到程序一系列的約束條件 ,然後使用 SMT Solver合成語句。

到了2014年,ICSE上,這個問題依舊很火。法國人提出NOPOL,又把問題局限到只修復if條件語句的Bug,說實話也就是換了層馬甲,用得方法還是Symbolic Execution+SMT Solver

RSRepair

還是在2014的ICSE上,國防科大提出了RSRepair(首次看見國人在這方向發文章)。其實作者沒沒做太多的工作,還記得上面GenProg嗎?GenProg方法使用遺傳演算法,裡面有mutation和crossover兩步,他也就把crossover那一步去掉了,然後聲稱這樣的修復結果比GenProg還要好(作者挑了GenProg的部分實驗程序做的實驗,說自己24個程序全部都可以修復)。

好,下面是學術界sibi時間。。。

時間到了2015年,今天一開學,我搜文獻一看,發現一個大新聞:MIT的CSAIL(就是Code Phage同組)的技術報告上說,他們發現GenProg的實驗有問題!GenProg驗證程序是否修復,不是通過驗證test case的輸入輸出的,而是檢驗程序是否最終成功exit(0)!也就是說,程序只要不會crash就行。他們重現了GenProg,嚴格地檢驗了GenProg的修復結果,發現只能在105個裡面修復3個,大部分GenProg生成可以修復bug的程序基本上都是刪除了一些核心代碼,實際並沒有修復。當然,RSRepair也未能脫離厄運,其結果被驗證出來也是慘不忍睹。

好玩的是,在今年的FSE上,Claire Le Goues(Genprog的主力作者)發文章(作為通訊作者),說GenProg可能存在overfitting的情況,但並沒有提及自己實驗設計的問題。

然後MIT針對bug自動修復還有另外兩個研究思路,一個今年發了FSE,叫做staged program repair,也用到了很多黑科技,實驗做得轟轟烈烈,進展也很快(我也尚在研讀)。另一個就是提出提到的Code Phage,已經發了PLDI。

當然,我上面提到的方法基本都是基於源碼與測試用例的方法,此外在09年MIT就提出了binary層面上的修復,而後還有一些針對特定錯誤類型的修復(比如integer overflow),還有針對並發程序bug的修復等等。。。

扯完了這麼多,我想對bug的自動修復的未來做一個展望。首先,這是一個很困難的問題,在未來的幾十年裡面都很難徹底解決。但是一些新鮮的方法會層出不窮,尤其是現在在MIT的帶領下,大家的熱情應該會繼續高漲。然後,就會有人將現有的方法做個融合,實現出一個大型的修復系統(MIT似乎就由這個計劃)。總之,我還是對bug自動修復的為了充滿了期待的。只可惜姿勢水平不足,目前尚無清晰的思路,還請各路大神進行點播。


經人推薦才發現知乎上居然有這樣一個問題,看來缺陷自動修復技術大家關注還是比較多的。先自我介紹一下,我是北京大學的,國內做缺陷自動修復研究的我們應該是最大的一個團隊。2015年我們在ASE發表的QAFix是目前全球所有程序缺陷修復系統中正確率最高的,同時我們還做過內存泄露修復、配置修復、設計模型修復、網頁表示缺陷修復等一系列特定缺陷的技術。

至於CodePhage系統,我只能說是MIT的新聞宣傳做得比較好。實際上CodePhage在學術領域影響是比較小的,原因是這個系統只能修復一些特定類型的缺陷,方法並不通用,同時實驗驗證規模相比同期的一些工作明顯要小。MIT那個團隊實際影響比較大的工作是清華天才畢業生龍凡同學的SPR和Prophet,不過那這兩篇對應的新聞似乎反而沒有廣泛傳播。

至於缺陷修復整個領域來說,要替代程序員還有很長很長的路要走。目前能修復的只有真實系統中10%左右的缺陷,而且所產生的修復的正確率一般都不超過50%(我們的QAFix能有80%的正確率,但修復的缺陷數少了很多)。這樣低的正確率在實際系統中完全是不能用的,最後還是要靠程序員手動修復。

前面其他回答講了很多國外的工作,實際上國內還是有很多研究人員在做缺陷修復的工作。但因為中國學術實力還不夠強,這些工作被關注程度遠不如國外。除了我們團隊和其他回答中提到的國防科大毛曉光老師有以外,還有武漢大學的玄躋峰老師,他是前面提到的法國NOPOL的作者,以及上海交大的鐘浩老師,他在2015年的ICSE上發表了一篇關於缺陷有多難被自動修復的實證研究文章。


我大麻校的宣傳部門是一等一的,每個季度都會有專門的宣宣人員深入到田間地頭各個實驗室,詢問最近有沒有什麼新發的paper或者可以吹吹的項目。然後各個媒體(尤其是wired之類的網路媒體)也都是盯著我大麻校的宣宣。當然記者們寫出來的東西最後往往是面目全非,原作者看了都懵逼。但這不妨礙向普羅大眾推廣,因為你給個paper他們也看不懂啊。重要的是讓人知道我大麻校的人不是成天吃free food浪費錢,是真的做了好多高大上的研究。

至於說這個項目本身,或者說Martin組整個的program repair方向,我個人的觀點:學術上絕對是很牛逼很有價值的,工程實現上肯定也是吃了很多翔蹚平了很多坑才能做出paper裡面的效果,但是什麼時候這方法能推廣並實用?不知道。一是科學研究跟實際應用之間本身就有挺大距離,二是工程人員的平均能力畢竟比龍少這種人差太遠。


"黑"科技


看一下paper吧,並不一定需要代碼。

有點仿生學的味道。

關鍵是要修正bug,需要找合適的donor applications,這個本身也是個問題啊。

tracking是基友Valgrind binary analysis framework的。

這個paper思路和做法都很強,但是遠非任何bug都能自動修復-------------在目前說任何bug都能自動修復的這話的,就是徹頭徹尾的民科或者是跳大神的神棍。


我不信它能理解"這並不是bug,而是一個feature"這種高深的信仰


不發表評論。

這還不是 CodePhage 最「黑科技」的地方。CodePhage 能夠在沒有獲取訪問源代碼許可權的前提下尋找適合的代碼,然後以相同的前提對 BUG 程序進行不斷的調試,直至找到最理想的修復代碼為止。

沒有獲取訪問源代碼許可權的前提下尋找適合的代碼, 是否意味WINDOWS 的BUG也能修復.


推薦閱讀:

寫 patch 修復了一個軟體的 bug,卻被拒絕合併是一種怎樣的體驗?
守望先鋒有哪些有趣的bug?
玩一些遊戲切換出去之後就無法再次運行的原因是什麼?
爐石傳說12.11任務無法接取的bug是怎麼回事?
如何看待陰陽師業火原bug事件?

TAG:編程 | Bug |