專利名稱:源代碼靜態(tài)分析模擬器的自定義api建模的制作方法
技術(shù)領(lǐng)域:
本發(fā)明一般涉及計(jì)算機(jī)軟件開發(fā),尤其涉及用于改進(jìn)計(jì)算機(jī)源代碼的評(píng)估來檢測編程錯(cuò)誤的方法和系統(tǒng)。
背景技術(shù):
過去幾十年中,微處理器、隨機(jī)存儲(chǔ)存儲(chǔ)器(RAM)和存儲(chǔ)系統(tǒng)的日益改進(jìn)的性價(jià)比影響了如何開發(fā)計(jì)算機(jī)軟件。過去,在硬件資源更昂貴的時(shí)候,通常以匯編語言編寫源代碼。以低級(jí)語言編寫代碼對(duì)開發(fā)員而言是較耗時(shí)的,但是結(jié)果得到更有效和緊湊的代碼。然而,作為處理器、存儲(chǔ)器和存儲(chǔ)的日益改進(jìn)的性價(jià)比的結(jié)果,更多的程序設(shè)計(jì)是以諸如C/C++、Visual Basic等高級(jí)語言執(zhí)行的,來最小化軟件開發(fā)的成本。
已經(jīng)為軟件開發(fā)員創(chuàng)建了更好的工具,這些工具使得軟件創(chuàng)建更有效和多產(chǎn),并進(jìn)一步利用可用的改進(jìn)計(jì)算系統(tǒng)。例如,靜態(tài)源代碼分析工具幫助軟件開發(fā)員通過推斷源代碼的可能行為來標(biāo)識(shí)錯(cuò)誤。某些靜態(tài)源代碼分析工具編譯代碼來標(biāo)識(shí)常規(guī)編譯器可能無法檢測到的導(dǎo)致違背程序設(shè)計(jì)語言規(guī)則的句法缺陷。某些靜態(tài)源代碼分析工具不包括編譯器,但是相反,截取外部編譯器的輸出,解析經(jīng)編譯的代碼并分析它。一旦靜態(tài)源代碼分析工具評(píng)估了源代碼以找出可能的句法錯(cuò)誤之后,由代碼分析器生成的源代碼的表示還允許模擬器評(píng)估代碼以找出語義問題。因此,靜態(tài)源代碼分析工具幫助檢測編譯器可能沒有檢測到的句法錯(cuò)誤,以及編譯器不能檢測的語義錯(cuò)誤。
圖1A示出了常規(guī)(現(xiàn)有技術(shù))靜態(tài)源代碼分析器100a的框圖。由軟件開發(fā)員準(zhǔn)備的源代碼102a是靜態(tài)源代碼分析器100a的輸入。源代碼首先由輸入處理器104a解析,它忽略頭部塊和注釋,將源代碼精簡為提交給模擬器108a的標(biāo)準(zhǔn)程序設(shè)計(jì)指令106a的列表。模擬器108標(biāo)識(shí)源代碼中的句法和語義錯(cuò)誤。例如,誤用、拼錯(cuò)或不含有適當(dāng)?shù)膮?shù)或定界符的表達(dá)式被標(biāo)識(shí)為句法錯(cuò)誤。另外,模擬器108a標(biāo)識(shí)除文字或句法之外的錯(cuò)誤。例如,如果源代碼訪問不能被適當(dāng)?shù)貑?dòng)的存儲(chǔ)器,那么模擬器108a標(biāo)識(shí)該錯(cuò)誤。又例如,如果源代碼請求初始化變量,且變量在某個(gè)界限內(nèi),但是該變量沒有被初始化或者由于該變量的值超出預(yù)定的界限而無效,那么模擬器108a也標(biāo)識(shí)錯(cuò)誤。由模擬器108a標(biāo)識(shí)的錯(cuò)誤在可由軟件開發(fā)員用來修改和修復(fù)其源代碼的錯(cuò)誤報(bào)告110a中呈現(xiàn)。
圖1B示出了來自現(xiàn)有的源代碼分析器的示例性屏幕120。在該源代碼分析器中,在源代碼窗口124中可查看被提交以供分析的源代碼122,而在分析窗口128中呈現(xiàn)出錯(cuò)消息126。出錯(cuò)消息126包括與源代碼122中的行132的相關(guān)性130以協(xié)助軟件開發(fā)員更正錯(cuò)誤。
靜態(tài)源代碼分析器對(duì)軟件開發(fā)員非常有幫助,因?yàn)樗鼈儏f(xié)助軟件開發(fā)員標(biāo)識(shí)可能干擾源代碼的編譯,或者即使源代碼平安無事地編譯了,仍舊可能使得軟件在操作過程中失敗的問題。靜態(tài)源代碼分析器不代替測試來確定所得到的軟件是否按照預(yù)期的方式工作。然而,通過向開發(fā)員呈現(xiàn)包含與源代碼122中的特定行132的相關(guān)性的出錯(cuò)消息126,靜態(tài)源代碼分析器允許開發(fā)員快速地定位其源代碼中的潛在的句法和語義問題。
靜態(tài)源代碼分析器的準(zhǔn)確性取決于它們解釋所呈現(xiàn)的源代碼的能力。作為結(jié)構(gòu),可能遺漏源代碼中的某些錯(cuò)誤。另外,如果靜態(tài)源代碼分析器不正確地解釋了正被分析的源代碼,那么當(dāng)被評(píng)估的源代碼是正確的時(shí)候可能會(huì)生成假肯定。不幸的是,假肯定的出現(xiàn)累計(jì)為使得指示源代碼中實(shí)際錯(cuò)誤的出錯(cuò)消息變得模糊的噪聲。結(jié)果是,被分析的軟件代碼中的實(shí)際錯(cuò)誤可能被軟件開發(fā)員忽略。
對(duì)軟件開發(fā)員很有幫助的其它工具是軟件開發(fā)員工具包。軟件開發(fā)員工具包一般是為諸如Microsoft WINDOWSTM等特定操作系統(tǒng),或諸如Microsoft XBOXTM等計(jì)算或游戲平臺(tái)創(chuàng)建的,以通過允許對(duì)之前創(chuàng)建的軟件工具的訪問而使軟件開發(fā)變得更容易。這些軟件開發(fā)包可以包括執(zhí)行可能被開發(fā)員包含在其代碼中的公共函數(shù)的預(yù)寫例程的源代碼。通過提供對(duì)這樣的軟件例程的方便的訪問,開發(fā)員不必浪費(fèi)時(shí)間來重新編寫已經(jīng)創(chuàng)建的公共例程。
軟件開發(fā)工具包也可以包括可在開發(fā)員為其創(chuàng)建軟件的操作系統(tǒng)中訪問的應(yīng)用程序接口或應(yīng)用程序編程接口(API)。API可以被用來調(diào)用服務(wù)以生成圖形、生成聲音和任何數(shù)量的其它功能。另外,調(diào)用不同地實(shí)現(xiàn)但功能可比的服務(wù)的API可以用來提供可為其編譯源代碼的不同平臺(tái)之間的源代碼可移植性??赡茏钪匾氖?,API可用于提供高級(jí)語言源代碼和與操作環(huán)境的硬件設(shè)備更直接操作的較低級(jí)實(shí)用程序之間的接口。
在二進(jìn)制代碼庫的集合中,API通常離散分布,或者作為軟件開發(fā)工具包的一部分。一般,用于創(chuàng)建API的源代碼不是分布的,或以其它方式使其對(duì)開發(fā)員可用。源代碼不可用于保護(hù)操作環(huán)境的開發(fā)員的各種私人考慮。然而,即使API的源代碼實(shí)現(xiàn)不可用,使用解釋API操作、調(diào)用API的正確句法、傳遞給API的參數(shù)和由API返回的值的特征的軟件開發(fā)工具包,文檔或其它信息仍可以是可用的。
不幸的是,向靜態(tài)源代碼分析器提交調(diào)用一個(gè)或多個(gè)API的源代碼可能導(dǎo)致生成多個(gè)錯(cuò)誤。如上所述,源代碼分析器僅在它被配置成理解源代碼的情況下才是準(zhǔn)確的。因此,靜態(tài)源代碼分析器可能無法分析API簽名,因?yàn)閮H向源代碼分析器提供API簽名,而源代碼分析器不能訪問API的源代碼實(shí)現(xiàn)。
如在圖1C的現(xiàn)有示例中示出,當(dāng)分析源代碼102c時(shí),靜態(tài)源代碼分析器100c的輸入處理器104c將API簽名152識(shí)別為與標(biāo)準(zhǔn)程序設(shè)計(jì)指令106c不同。API簽名152可被認(rèn)為是出錯(cuò)報(bào)告110c中的句法錯(cuò)誤,因?yàn)锳PI簽名表示了非標(biāo)準(zhǔn)的表達(dá)式?;蛘?,例如在C++中,可以向API簽名152追加“extern”指定,它將阻止模擬器108c試圖評(píng)估API簽名152的語義。無需API的源代碼實(shí)現(xiàn),靜態(tài)源代碼分析器就能夠通過根據(jù)API簽名確定是否向API傳遞適當(dāng)?shù)膮?shù)來評(píng)估API調(diào)用的句法。然而,在沒有源代碼的情況下,靜態(tài)源代碼分析器不能在語義上評(píng)估API簽名152、它們的行為及它們對(duì)調(diào)用API簽名152的源代碼的效果。在遇到“extern”指定之后,靜態(tài)源代碼分析器不試圖在語義上評(píng)估隨后的表達(dá)式。
在不訪問API的源代碼實(shí)現(xiàn)的情況下,靜態(tài)源代碼分析器不能確定API可能具有的效果,例如在傳遞給API的參數(shù)上的效果。結(jié)果是,當(dāng)一帶有變量的問題實(shí)際關(guān)于該API時(shí),靜態(tài)源代碼分析器108c可能生成關(guān)于該問題的出錯(cuò)消息。結(jié)果是,源代碼中的API的內(nèi)容可能導(dǎo)致大量的假肯定出錯(cuò)消息,即由源代碼分析器生成的噪聲,不幸的是,這可能將注意力從實(shí)際的真正出錯(cuò)消息移開。另外,因?yàn)樵创a分析器可能無法評(píng)估API調(diào)用或其效果,所以源代碼分析器可能無法檢測由這樣的API調(diào)用導(dǎo)致的錯(cuò)誤。API可以在傳遞給它的參數(shù)上執(zhí)行操作,該操作將導(dǎo)致源代碼中某個(gè)后繼點(diǎn)處的非法操作。因此,如果源代碼分析器不能夠評(píng)估API的操作,那么源代碼分析器可能無法檢測到源代碼中的相關(guān)錯(cuò)誤。
從而,期望提供即使不必訪問API的源代碼實(shí)現(xiàn)也能夠評(píng)估API調(diào)用的方法和系統(tǒng)。
發(fā)明內(nèi)容
從而,本發(fā)明的一個(gè)優(yōu)點(diǎn)是,它提供了用于即使在外部函數(shù)調(diào)用的源代碼實(shí)現(xiàn)不可用的情況下,也能評(píng)估諸如API調(diào)用等外部函數(shù)調(diào)用的方法和系統(tǒng)。通常,已知的源代碼分析器忽略外部函數(shù)調(diào)用,且作為結(jié)果,可能錯(cuò)過外部函數(shù)調(diào)用中的錯(cuò)誤,或者當(dāng)實(shí)際上檢測到的錯(cuò)誤由外部函數(shù)調(diào)用解決時(shí)標(biāo)記假肯定。因?yàn)橥獠亢瘮?shù)的源代碼不可用,不能將函數(shù)源代碼本身包含在源代碼中并對(duì)其分析。然而,因?yàn)楹瘮?shù)源代碼不可用,外部函數(shù)的提供者可能提供描述外部函數(shù)操作的文檔或其它信息。該文檔使得軟件開發(fā)員能夠理解向該外部函數(shù)傳遞什么參數(shù)、該外部函數(shù)輸出什么參數(shù)、API取決于什么先決函數(shù)、以及其它重要的信息。從該描述性的信息中,可以開發(fā)模型來確保恰當(dāng)?shù)卣{(diào)用了API。根據(jù)本發(fā)明的一個(gè)實(shí)施例,伴隨靜態(tài)源代碼分析器所包含的一組原語向用戶提供了對(duì)API功能建模的方式,使得源代碼分析器能夠評(píng)估API調(diào)用的行為和效果。
因此,本發(fā)明的一個(gè)方面針對(duì)用于分析函數(shù)源代碼實(shí)現(xiàn)不可用的外部函數(shù)的調(diào)用的方法。標(biāo)識(shí)由源代碼對(duì)外部函數(shù)的不恰當(dāng)調(diào)用導(dǎo)致的至少一個(gè)潛在錯(cuò)誤,并標(biāo)識(shí)將導(dǎo)致該潛在錯(cuò)誤的至少一個(gè)條件。使用了可用于測試導(dǎo)致潛在錯(cuò)誤的至少一個(gè)條件,且當(dāng)發(fā)現(xiàn)條件時(shí)能夠啟動(dòng)生成出錯(cuò)消息的外部函數(shù)的模型。該模型與源代碼分析器相關(guān)聯(lián),使得當(dāng)由源代碼分析器分析源代碼時(shí),該模型被應(yīng)用來評(píng)估外部函數(shù)的調(diào)用或操作。
外部函數(shù)可以包括API?;诿枋鐾獠亢瘮?shù)的操作的信息來對(duì)可能導(dǎo)致潛在錯(cuò)誤的至少一個(gè)條件進(jìn)行標(biāo)識(shí)。條件可以包括應(yīng)用程序編程接口可接受的輸入?yún)?shù)的不正確輸入類型,或者API可接受的輸入?yún)?shù)的不正確輸入內(nèi)容范圍。類似地,條件可以包括可由API生成的輸出參數(shù)的不正確輸出,或可由API生成的輸出參數(shù)的不正確輸出內(nèi)容范圍。條件也可以包括不能調(diào)用在調(diào)用外部函數(shù)之前必須被調(diào)用的先決函數(shù),或不能調(diào)用在調(diào)用外部函數(shù)之后必須被調(diào)用的后決函數(shù)。
可以使用可用于測試導(dǎo)致潛在錯(cuò)誤的至少一個(gè)條件的多個(gè)原語來創(chuàng)建模型。源代碼分析器包括被配置成存儲(chǔ)所創(chuàng)建的模型的模型儲(chǔ)存庫,使得源代碼分析器能夠在評(píng)估源代碼并標(biāo)識(shí)對(duì)外部函數(shù)的引用之后訪問該模型。
當(dāng)結(jié)合附圖參考以下詳細(xì)描述時(shí),可以更容易且更好地領(lǐng)會(huì)和理解本發(fā)明的前述方面和眾多附加優(yōu)點(diǎn),附圖中圖1A(現(xiàn)有技術(shù))是典型的靜態(tài)源代碼分析器的功能框圖;
圖1B(現(xiàn)有技術(shù))是來自典型的靜態(tài)源代碼分析器的屏幕;圖1C(現(xiàn)有技術(shù))是面對(duì)API簽名的典型的靜態(tài)源代碼分析器的功能框圖;圖2是適用于使用本發(fā)明的一個(gè)實(shí)施例的計(jì)算設(shè)備或個(gè)人計(jì)算機(jī)(PC)的功能框圖;圖3是使用本發(fā)明的一個(gè)實(shí)施例來評(píng)估API簽名的靜態(tài)源代碼分析器的功能框圖;圖4是示出用于為靜態(tài)源代碼分析器創(chuàng)建API模型的邏輯步驟的流程圖;圖5是對(duì)從API的功能的描述中導(dǎo)出的API功能建模的狀態(tài)對(duì)象的狀態(tài)圖;圖6A和6B(現(xiàn)有技術(shù))是來自在假定傳遞給API的參數(shù)不是由該API的初始化的情況下配置的靜態(tài)源代碼分析器的屏幕;圖7A和7B(現(xiàn)有技術(shù))是來自假定傳遞給API的參數(shù)是由該API的初始化的情況下配置的靜態(tài)源代碼分析器的屏幕;圖8A和8B是來自使用本發(fā)明的一個(gè)實(shí)施例來對(duì)API的功能建模的靜態(tài)源代碼分析器的屏幕;以及圖9是示出根據(jù)本發(fā)明的一個(gè)實(shí)施例,用于分析源代碼的邏輯步驟的流程圖。
具體實(shí)施例方式
用于實(shí)現(xiàn)本發(fā)明的示例性計(jì)算系統(tǒng)參考圖2,示出了適用于本發(fā)明的實(shí)施例的示例性常規(guī)計(jì)算系統(tǒng)。該系統(tǒng)包括形式為PC 220a的通用計(jì)算設(shè)備,PC 220a裝備有處理單元221、系統(tǒng)存儲(chǔ)器222和系統(tǒng)總線223。系統(tǒng)總線將包括系統(tǒng)存儲(chǔ)器在內(nèi)的各種系統(tǒng)組件耦合至處理單元221,且可以是若干類型的總線結(jié)構(gòu)中的任一種,包括存儲(chǔ)器總線或存儲(chǔ)器控制器、外圍總線和使用各種總線體系結(jié)構(gòu)中的任一種的局部總線。系統(tǒng)存儲(chǔ)器包括只讀存儲(chǔ)器(ROM)224和隨機(jī)存取存儲(chǔ)器(RAM)225?;据斎?輸出系統(tǒng)(BIOS)226包含有助于諸如啟動(dòng)時(shí)PC 220中元件之間傳遞信息的基本例程,它通常存儲(chǔ)在ROM 224中。PC 220還可以包括用于從硬盤(未示出)中讀取或向其寫入的硬盤驅(qū)動(dòng)器227,用于從可移動(dòng)磁盤229中讀取或向其寫入的磁盤驅(qū)動(dòng)器228,以及用于從諸如光盤只讀存儲(chǔ)器(CD ROM)或其它光學(xué)介質(zhì)等可移動(dòng)光盤231中讀取或向其寫入的光盤驅(qū)動(dòng)器230。硬盤驅(qū)動(dòng)器227、磁盤驅(qū)動(dòng)器228和光盤驅(qū)動(dòng)器230分別由硬盤驅(qū)動(dòng)器接口232、磁盤驅(qū)動(dòng)器接口233和光盤驅(qū)動(dòng)器接口234連接至系統(tǒng)總線223。驅(qū)動(dòng)器及其相關(guān)聯(lián)的計(jì)算機(jī)可讀介質(zhì)為PC 220提供了對(duì)計(jì)算機(jī)可讀機(jī)器指令、數(shù)據(jù)結(jié)構(gòu)、程序模塊和其它數(shù)據(jù)的非易失性存儲(chǔ)。盡管此處所述的示例性環(huán)境使用硬盤、可移動(dòng)磁盤229和可移動(dòng)光盤231,但是本領(lǐng)域的其它技術(shù)人員可以理解,也可以在示例性操作環(huán)境中使用用于存儲(chǔ)可由計(jì)算機(jī)訪問的數(shù)據(jù)和機(jī)器指令的其它類型的計(jì)算機(jī)可讀介質(zhì),諸如盒式磁帶、閃存卡、數(shù)字多功能盤(DVD)、貝努利盒式磁盤、RAM、ROM等。
可以在硬盤、磁盤229、光盤231、ROM 224或RAM 225上存儲(chǔ)包括操作系統(tǒng)235、一個(gè)或多個(gè)應(yīng)用程序模塊236、其它程序模塊237和程序數(shù)據(jù)238的多個(gè)程序模塊。用戶可以通過諸如經(jīng)由I/O設(shè)備接口246與系統(tǒng)總線223通信的鍵盤240和定點(diǎn)設(shè)備242向PC 220輸入命令和信息并提供控制輸入。定點(diǎn)設(shè)備242可以包括鼠標(biāo)、指示筆、無線遙控器、或其它指示器,但是關(guān)于本發(fā)明,可以省略這樣的常規(guī)定點(diǎn)設(shè)備,因?yàn)橛脩艨梢允褂媒换ワ@示用于輸入和控制。如在下文中所使用的,術(shù)語“鼠標(biāo)”旨在包含可用于控制屏幕上光標(biāo)位置的基本上任何定點(diǎn)設(shè)備。一個(gè)或多個(gè)音頻輸入/輸出設(shè)備243,包括耳機(jī)、揚(yáng)聲器和麥克風(fēng),也經(jīng)由I/O設(shè)備接口246加入個(gè)人計(jì)算機(jī)220。其它輸入設(shè)備(未示出)可以包括操縱桿、觸覺操縱桿、偏轉(zhuǎn)系統(tǒng)、腳踏板、游戲墊、圓盤式衛(wèi)星天線、掃描儀等。這些和其它輸入/輸出(I/O)設(shè)備通常由耦合至系統(tǒng)總線223的I/O接口246連接至處理單元221。術(shù)語I/O接口旨在包含專供串行端口、并行端口、游戲端口、鍵盤端口和/或通用串行總線(USB)使用的每一接口。監(jiān)視器247經(jīng)由諸如視頻適配器248等合適的接口連接至系統(tǒng)總線223??梢岳斫猓琍C通常耦合至其它外圍輸出設(shè)備(未示出),諸如揚(yáng)聲器(經(jīng)由聲卡或其它音頻接口(未示出))和打印機(jī)。
PC 220可使用至一臺(tái)或多臺(tái)遠(yuǎn)程計(jì)算機(jī),諸如遠(yuǎn)程計(jì)算機(jī)249的邏輯連接在網(wǎng)絡(luò)化環(huán)境中操作。遠(yuǎn)程計(jì)算機(jī)249可以是另一臺(tái)PC、服務(wù)器(通常一般被配置成與PC 220a非常類似)、路由器、網(wǎng)絡(luò)PC、對(duì)等設(shè)備、衛(wèi)星或其它常見網(wǎng)絡(luò)節(jié)點(diǎn),且通常包括上文相對(duì)于PC 220a描述的許多或所有元件,盡管在圖2中只示出外部存儲(chǔ)器存儲(chǔ)設(shè)備250。圖2中所示邏輯連接包括局域網(wǎng)(LAN)251和廣域網(wǎng)(WAN)252。這樣的網(wǎng)絡(luò)環(huán)境在辦公室、企業(yè)范圍計(jì)算機(jī)網(wǎng)絡(luò)、內(nèi)聯(lián)網(wǎng)和因特網(wǎng)中是常見的。
當(dāng)在LAN網(wǎng)絡(luò)環(huán)境中使用時(shí),PC 220通過網(wǎng)絡(luò)接口或適配器253連接至局域網(wǎng)251。當(dāng)在WAN網(wǎng)絡(luò)環(huán)境中使用時(shí),PC 220通常包括調(diào)制解調(diào)器254或用于通過諸如因特網(wǎng)的WAN 252建立通信的其它裝置,諸如線纜調(diào)制解調(diào)器、數(shù)字用戶線路(DSL)接口、或綜合業(yè)務(wù)數(shù)字網(wǎng)絡(luò)(ISDN)接口。調(diào)制解調(diào)器254可以是內(nèi)置或外置的,它通過I/O設(shè)備接口246(即,通過串行端口)連接至或耦合至系統(tǒng)總線223。在網(wǎng)絡(luò)化環(huán)境中,由PC 220使用的程序模塊或其部分可以存儲(chǔ)在遠(yuǎn)程存儲(chǔ)器存儲(chǔ)設(shè)備中。可以理解,所示的網(wǎng)絡(luò)連接是示例性的,且可以使用在計(jì)算機(jī)之間建立通信鏈路的其它手段,諸如無線通信和寬頻網(wǎng)絡(luò)鏈路。
適用于評(píng)估API的源代碼分析器圖3示出了靜態(tài)源代碼分析器300的框圖,它包括如上結(jié)合圖1A和1C所述的常規(guī)靜態(tài)源代碼分析器的某些屬性。由軟件開發(fā)員準(zhǔn)備源代碼302,并將其提交給靜態(tài)源代碼分析器300以檢測潛在的錯(cuò)誤。源代碼由輸入處理器304解析。輸入處理器忽略注釋、頭部塊、帶有“extern(外部)”或類似句法前綴的行等,從而表示由模擬器308分析的標(biāo)準(zhǔn)程序設(shè)計(jì)指令306。另外,可以由處理器304識(shí)別一個(gè)或多個(gè)外部函數(shù)調(diào)用或API簽名352。在隨后的描述中,調(diào)用的外部函數(shù)被描述為API。盡管如此,本發(fā)明的實(shí)施例可用于評(píng)估可能由其源代碼對(duì)靜態(tài)源代碼分析不可用的其它外部函數(shù)調(diào)用的不正確調(diào)用或操作引起的錯(cuò)誤。
如上所述,照常規(guī),向API簽名的聲明追加指定“extern”或類似的標(biāo)識(shí)符指示,表示API的表達(dá)式調(diào)用源代碼實(shí)現(xiàn)不可用的外部例程。如在本領(lǐng)域中可以理解,“extern”指定傳遞至編譯器,而不試圖解決該外部例程的任何后繼調(diào)用。鏈接程序?qū)⒇?fù)責(zé)定位所調(diào)用的函數(shù)的目標(biāo)代碼,以及編譯之后在二進(jìn)制代碼級(jí)上解決該外部函數(shù)的代碼實(shí)現(xiàn)。另外,“extern”指定傳遞至常規(guī)靜態(tài)源代碼分析器,而不試圖在語義上分析該被指定的外部函數(shù)。盡管如此,靜態(tài)源代碼分析器仍舊可以評(píng)估后繼外部函數(shù)調(diào)用的句法,以確保外部函數(shù)的調(diào)用符合指定的函數(shù)的句法。
根據(jù)本發(fā)明的各實(shí)施例,所標(biāo)識(shí)的潛在的API簽名352被提交給API模擬器360。API模擬器360評(píng)估潛在的API簽名352,以確定句法是否正確,是否向API傳遞了恰當(dāng)?shù)膮?shù),傳遞的參數(shù)是否是適當(dāng)類型的,并以其它方式評(píng)估API簽名352是否存在編碼錯(cuò)誤。由API模擬器360向模擬器308傳遞對(duì)API簽名352是否是正確形式的判斷。使用由API模擬器360提供的信息,模擬器308在出錯(cuò)報(bào)告310中生成包含錯(cuò)誤的API簽名352的出錯(cuò)消息。相反,可能被模擬器308標(biāo)記為錯(cuò)誤的假肯定由于其缺乏與API簽名352的熟悉性,在出錯(cuò)報(bào)告310中不被報(bào)告為錯(cuò)誤。
可以理解,如果API的源代碼實(shí)現(xiàn)對(duì)軟件開發(fā)員可用,那么軟件開發(fā)員可以在軟件開發(fā)員的源代碼302中合并API源代碼實(shí)現(xiàn),以及源代碼302的其余部分,以供模擬器308評(píng)估。然而,如上所述,一般而言,在使得API能夠與從源代碼302編譯而來的其它目標(biāo)代碼模塊鏈接的二進(jìn)制代碼庫中,僅以其目標(biāo)代碼形式提供API。有利的是,本發(fā)明的實(shí)施例不需API的提供者供應(yīng)API的源代碼實(shí)現(xiàn)。
而是相反,對(duì)所構(gòu)想、預(yù)期或期望與源代碼302一起使用的每一API簽名,API模擬器360包括對(duì)每一API簽名的評(píng)估的模型。例如,可以為標(biāo)識(shí)為最有可能調(diào)用的一組API開發(fā)模型。結(jié)果是,可以清除由于假肯定而可能被包含在出錯(cuò)報(bào)告310中的大多數(shù)噪聲,而不必包含可能被調(diào)用的每個(gè)API的模型。
API模擬器360包括源自較佳地由API開發(fā)員在對(duì)軟件開發(fā)員可用的SDK和/或API文檔380中提供的信息的模型。一般而言,SDK/API文檔380描述API的功能、指示要向API提供的參數(shù),API所需或所用的值的形式、以及API的其它功能特征。SDK/API文檔380用于使用API原語370對(duì)API建模。API原語370包括打包在與可由用戶用來對(duì)API的功能建模的模擬器相關(guān)聯(lián)的建模庫中的一組例程,使得API模擬器360可以評(píng)估由源代碼調(diào)用的API的效果。以下進(jìn)一步描述API原語370的使用。
因此,通過使用API原語370及審閱SDK/API文檔380,即使不訪問API源代碼,也可以推出某些規(guī)則來評(píng)估可能被包含在提交給靜態(tài)源代碼分析器300的源代碼302中的API簽名352的調(diào)用和/或操作。這些規(guī)則可以被包含在API模擬器360中,且可以被應(yīng)用于所標(biāo)識(shí)的潛在API簽名352。然后評(píng)估所標(biāo)識(shí)的API簽名,來確定它們是否使用了適當(dāng)?shù)木浞ā⑾駻PI傳遞了適當(dāng)?shù)膮?shù)、及是否在其它方面遵循API的規(guī)則,以評(píng)估源代碼302中的API簽名是否有效。如果API模擬器360被應(yīng)用來確定在源代碼中標(biāo)識(shí)的API簽名352是否被正確地實(shí)現(xiàn),那么在出錯(cuò)報(bào)告310中將不報(bào)告任何出錯(cuò)消息。另一方面,如果在源代碼302中存在調(diào)用API的錯(cuò)誤,那么API模擬器360將該出錯(cuò)消息傳達(dá)給模擬器308。因此,模擬器308可以在出錯(cuò)報(bào)告310中包括關(guān)于在源代碼302中標(biāo)識(shí)的API簽名的適當(dāng)?shù)某鲥e(cuò)消息。
較佳地,API模擬器360不僅評(píng)估API指示的獨(dú)立的句法和簽名的結(jié)構(gòu),而且也被配置成向模擬器308傳遞包含在源代碼302中的API簽名是否解決由模擬器308檢測到的源代碼302中的其它潛在錯(cuò)誤。作為一個(gè)簡單的示例,API可以評(píng)估傳遞給API的參數(shù),并對(duì)其值超過可接受值的某個(gè)限制的部分進(jìn)行截?cái)嗷蛏崛搿亩?,如果模擬器308檢測到特定值超出界限,則基于源代碼302,模擬器308可以查詢API模擬器360來確定API是否解決了該潛在的錯(cuò)誤。如果是,那么在出錯(cuò)報(bào)告310中將不報(bào)告任何出錯(cuò)消息,這進(jìn)一步減少了假肯定出錯(cuò)消息的發(fā)生率。
另外,包含在API模擬器中的API模型可以包括依賴性規(guī)則。例如,可能在調(diào)用API之前,必須初始化將被傳遞至API的參數(shù),或者必須調(diào)用API依賴的另一個(gè)API或某個(gè)其它函數(shù)。API模擬器360可以包括該依賴性規(guī)則,使得如果沒有在調(diào)用API之前調(diào)用依賴函數(shù),那么將由靜態(tài)源代碼分析器300生成錯(cuò)誤。類似地,如果調(diào)用API之后必須調(diào)用另一函數(shù)或API,那么API模擬器360也可以包括該規(guī)則,使得如果沒有按照所期望的方式調(diào)用該其它函數(shù)或API,那么生成錯(cuò)誤。
如上所述,眾多API是在二進(jìn)制代碼庫中提供的,且用于實(shí)現(xiàn)API的源代碼對(duì)將使用API的軟件開發(fā)員不可用。本發(fā)明模型的實(shí)施例基于由API或SDK提供的文檔來標(biāo)識(shí)預(yù)期的API,以使靜態(tài)源代碼分析器300能夠如下進(jìn)一步描述的來實(shí)質(zhì)上評(píng)估API調(diào)用。
可以理解,盡管靜態(tài)源代碼分析器300將輸入處理器304描述為使得標(biāo)準(zhǔn)程序設(shè)計(jì)指令和API簽名352被獨(dú)立地處理,但是模擬器308和API模擬器360最好協(xié)作工作來評(píng)估是否恰當(dāng)?shù)卣{(diào)用API,以及API是否與源代碼恰當(dāng)?shù)匕l(fā)揮作用。
示例性API的常規(guī)靜態(tài)源代碼分析器的處理為說明起見,呈現(xiàn)接收兩個(gè)參數(shù)并返回成功/失敗值的示例性API。在調(diào)用API之前,沒有初始化由第二參數(shù)指向的存儲(chǔ)器塊。API在由第二參數(shù)指向的存儲(chǔ)器塊上執(zhí)行某些操作。然而,如果第一參數(shù)沒有滿足某個(gè)條件,將不在由第二參數(shù)指向的存儲(chǔ)器塊上執(zhí)行函數(shù),實(shí)際上甚至不初始化該存儲(chǔ)器。從而,如果無法初始化存儲(chǔ)器塊是一個(gè)問題問題,則用于評(píng)估API效果的常規(guī)靜態(tài)源代碼分析器將不能檢測到該問題。
更具體地,示例性API使用以下API簽名和源代碼實(shí)現(xiàn)#define SOME_VALUE10bool SomeFunctionAPI(int a,int*b){if(a>0){*b=SOME_VALUE*a;
//沒有向開發(fā)員揭示其它代碼.
.
.
//沒有向開發(fā)員揭示其它代碼return true;
}
return false;
}無論由“其它代碼”執(zhí)行何種動(dòng)作,僅當(dāng)?shù)谝粎?shù)a大于零時(shí)才初始化b指向的存儲(chǔ)器塊,并對(duì)其作用。
進(jìn)一步假設(shè)API是由用戶期望提交用于靜態(tài)源代碼分析的源代碼引用的extern bool SomeFunctionAPI(int z,int*x)typedef signed int INT;
typedef void VOID;
VOID main(){INT q,x,y,z;
SOME_KNOWN_FUNCTION(q);
SomeFunctionAPI(z,&x);
y=I/x;
}靜態(tài)源代碼分析器不能訪問SomeFunctionAPI的源代碼實(shí)現(xiàn)。從而,常規(guī)的靜態(tài)源代碼分析器可以分析用于調(diào)用SomeFunctionAPI的句法,但是在不能訪問源代碼實(shí)現(xiàn)的情況下,將不評(píng)估API調(diào)用的語義。
在API調(diào)用之后的源代碼行y=1/x中出現(xiàn)潛在的問題。不能訪問API源代碼實(shí)現(xiàn)的常規(guī)靜態(tài)源代碼分析器不能確定API可能返回x的什么值。在檢查API的源代碼實(shí)現(xiàn)中,如果z大于零,將初始化x,但是如果z值小于或等于零,那么將不初始化x。不能以其它方式由調(diào)用API的源代碼初始化變量x。因此,如果沒有初始化x,那么表達(dá)式y(tǒng)=1/x會(huì)導(dǎo)致對(duì)未初始化變量的除法。另一方面,如果z大于或等于零,初始化x并將其置為非零值,那么表達(dá)式y(tǒng)=1/x將產(chǎn)生定義的、可接受的結(jié)果。而且即使能夠訪問源代碼實(shí)現(xiàn),即使沒有初始化z,也不可能預(yù)測API在值x上的結(jié)果。
某些常規(guī)模擬器可以進(jìn)行關(guān)于x的假設(shè)。例如,假設(shè)靜態(tài)源代碼分析器可以假定初始化了x。另一方面,靜態(tài)源代碼分析器也可以被配置成假定如果x沒有由調(diào)用API的源代碼初始化,那么x將不被API初始化。類似地,假設(shè)靜態(tài)源代碼分析器可以假定由API返回的x的值是零或不等于零。無論何種情況,靜態(tài)源代碼分析器僅可以猜測x的值,因?yàn)槌R?guī)靜態(tài)源代碼分析器不能確定將由API返回x的什么值。
結(jié)果是,因?yàn)槌R?guī)靜態(tài)源代碼分析器不能確定x的值,y=1/x表達(dá)式存在問題。如下進(jìn)一步描述的,取決于常規(guī)靜態(tài)源代碼分析器進(jìn)行了何種假定,靜態(tài)源代碼分析器將不能檢測錯(cuò)誤、生成假的出錯(cuò)消息或純粹偶然地產(chǎn)生適當(dāng)?shù)捻憫?yīng)。
根據(jù)本發(fā)明的實(shí)施例建模的示例性API即使API開發(fā)員沒有揭示API的源代碼實(shí)現(xiàn),根據(jù)本發(fā)明的實(shí)施例,靜態(tài)源代碼分析器仍適用于正確地標(biāo)識(shí)源代碼中潛在的錯(cuò)誤。
圖4示出了根據(jù)本發(fā)明,顯示用于對(duì)API建模的邏輯步驟。在步驟402處開始API建模。在步驟404處,審閱關(guān)于API功能的API文檔或其它信息?;谠搶?duì)API信息的審閱,在步驟406處,為API標(biāo)識(shí)恰當(dāng)?shù)木浞?。在步驟408處,標(biāo)識(shí)API的依賴性規(guī)則。例如,依賴性規(guī)則可以指定是否必須初始化由傳遞給API的指針?biāo)甘镜哪硞€(gè)參數(shù)或存儲(chǔ)器等,以及在API之后是否必須調(diào)用函數(shù)。在步驟410處,創(chuàng)建狀態(tài)對(duì)象來對(duì)API的功能和/或依賴性建模。在步驟412處結(jié)束API建模。
靜態(tài)源代碼分析器一般使用狀態(tài)對(duì)象來跟蹤程序元素和變量的狀態(tài)。因此,例如,在調(diào)用的API的前述例程中,如果調(diào)用了影響x的值的已知源代碼實(shí)現(xiàn)的函數(shù),那么可以使用狀態(tài)對(duì)象來跟蹤x的值以確定語句y=1/x中的除以x是否產(chǎn)生有效值。認(rèn)識(shí)了源代碼的已知句法和規(guī)則之后,可以使用狀態(tài)機(jī),例如,用于確定諸如無符號(hào)整數(shù)的原語是否以與作為無符號(hào)整數(shù)的原語一致的方式使用。
根據(jù)本發(fā)明的實(shí)施例,用戶可以研究描述API的文檔,以及使用API原語370(圖3)來創(chuàng)建靜態(tài)源代碼分析器可以訪問并評(píng)估AP的功能的模型。API原語370包括可以指定多個(gè)參數(shù)的簽名,簽名可以用于評(píng)估參數(shù)來確定它們是否滿足某些條件,以確定是否恰當(dāng)?shù)卣{(diào)用API、API是否產(chǎn)生有效的結(jié)果以及類似的判斷。
考慮示例性API,假定API文檔提供以下信息句法bool SomeFunctionAPI(int A,int*p B)參數(shù)A,是[in(入)]參數(shù),帶符號(hào)整數(shù),且必須被初始化為INT_MIN與INT_MAX之間的一個(gè)值。
pB,是[out(出)]參數(shù),指向帶符號(hào)整數(shù)的指針,且不能為NULL。
返回值如果該方法成功,則返回值為真;否則返回值為假。
功能基于參數(shù)A的值,初始化由參數(shù)pB指向的存儲(chǔ)器塊。
依賴性無限制-如果沒有初始化參數(shù)A,那么該方法的行為是未定義的。
-如果參數(shù)A被初始化為>0的值,那么由參數(shù)pB指向的存儲(chǔ)器塊被初始化為非零的值,該方法調(diào)用成功并返回真。
-如果參數(shù)A被初始化為<=0的值,那么不訪問由參數(shù)pB指向的存儲(chǔ)器塊,且如果之前沒有初始化則它可能保持未初始化,該方法失敗并返回假。
使用對(duì)API的功能的描述,以及關(guān)于使用API的限制,即使不能訪問源代碼實(shí)現(xiàn),根據(jù)本發(fā)明的實(shí)施例,靜態(tài)源代碼分析器仍舊可以對(duì)API的操作進(jìn)行建模和模擬。
如之前結(jié)合圖3所述,在本發(fā)明的一個(gè)實(shí)施例中,在建模庫中向靜態(tài)源代碼模擬器提供API原語使得靜態(tài)源代碼模擬器能夠?qū)PI行為建模。API原語涉及處理存儲(chǔ)器初始化、緩沖器、指針、存儲(chǔ)器分配的功能和可以由API執(zhí)行的其它功能。API原語可以用來指定當(dāng)調(diào)用API時(shí)必須保持的某些條件,以及當(dāng)對(duì)API的調(diào)用返回時(shí)被預(yù)期或保持為真的某些結(jié)果。
使用前述的API文檔,可以使用含有指定的原語簽名和函數(shù)的多個(gè)示例性API原語來建模API SomeFunctionAPI。例如,為四個(gè)API原語提供句法和功能描述,即使不能訪問源代碼實(shí)現(xiàn),這些API原語也可用來基于從API或SDK文檔已知的關(guān)于API的信息來對(duì)API功能建模,該描述如下CheckIntegerIsInitialized(int x)-驗(yàn)證x參數(shù)是否被初始化且在INT_MIN與INT_MAX的界限內(nèi)的原語簽名。如果整數(shù)參數(shù)x不滿足指定的條件,那么模擬器生成未初始化變量警告。
CheckIntegerBoundsGreaterEqual(int x,int lower_bound,iht upper_bound)-驗(yàn)證整數(shù)參數(shù)x的值大于或等于整數(shù)參數(shù)lower_bound(下界)的值,但小于或等于整數(shù)參數(shù)upper_bound(上界)的值的原語簽名。如果參數(shù)x不滿足該指定條件,那么模擬器生成越界警告。
CheckPointerIsValid(int*p)-驗(yàn)證指向整數(shù)變量的指針的參數(shù)p指向有效存儲(chǔ)器,從而驗(yàn)證該有效存儲(chǔ)器對(duì)數(shù)據(jù)存儲(chǔ)可用的原語簽名。如果整數(shù)指針不指向有效的存儲(chǔ)器,那么模擬器生成NULL指針解除引用警告。
ReturnIntegerValueGreaterThan(int*p,int lower_bound)-向模擬器指示指向整數(shù)變量的指針的參數(shù)p要被初始化為大于參數(shù)lower_bound的值的原語簽名。從而,當(dāng)模擬器解析在API調(diào)用之后涉及除以由指針p訪問的整數(shù)變量的表達(dá)式時(shí),模擬器將不會(huì)生成除以零或除以未定義值的警告。
可以理解,可以存在對(duì)應(yīng)于可能由API或其它外部函數(shù)執(zhí)行的任何數(shù)量的動(dòng)作的任何數(shù)量的API原語。
使用某些API原語,基于從API文檔獲取的關(guān)于API的信息,可以對(duì)APISomeFunctionAPI建模以便于靜態(tài)源代碼分析器對(duì)源代碼的更準(zhǔn)確評(píng)估bool SomeFunctionAPI(int a,int*b){CheckIntegerIsInitialized(a);
CheckIntegerBoundsGreaterEqual(a,1,INT_MAX);
CheckPointerIsValid(b);
ReturnIntegerValueGreaterThan(&b,0);}因此,當(dāng)模擬器標(biāo)識(shí)對(duì)SomeFunctionAPI的調(diào)用時(shí),模擬器API搜索由靜態(tài)源代碼模擬器檢查的模型的儲(chǔ)存庫。在為SomeFunctionAPI找到模型之后,訪問模型以協(xié)助評(píng)估源代碼的行為,包括由模型儲(chǔ)存庫中的模型表示的API的行為。從而,如下進(jìn)一步描述,靜態(tài)源代碼分析器能夠減少可能由不能訪問由源代碼調(diào)用的API的源代碼實(shí)現(xiàn)的靜態(tài)源代碼分析器生成的噪聲和假肯定出錯(cuò)消息。
表示API的潛在模型的狀態(tài)對(duì)象的圖形描述圖5是創(chuàng)建來對(duì)示例性API建模的狀態(tài)對(duì)象500的圖形描述。應(yīng)該注意,狀態(tài)對(duì)象僅使用API文檔中提供的信息,而擴(kuò)充靜態(tài)源代碼分析器以在源代碼上下文內(nèi)有意義地評(píng)估API調(diào)用的參數(shù)。
狀態(tài)對(duì)象500包括評(píng)估API調(diào)用的句法的狀態(tài)502。因?yàn)橥ㄟ^聲明API使用“extern”句法來將其指定為外部函數(shù),所以常規(guī)的靜態(tài)源代碼分析器將識(shí)別該“extern”句法調(diào)用源代碼不可用的模塊,并將忽略表達(dá)式的其余句法。從而,狀態(tài)502擴(kuò)充了靜態(tài)源代碼分析器,使得其能夠確定是否使用了API所定義的句法。狀態(tài)502可以包括順序測試以確定是否提供一連串所需參數(shù)的多個(gè)狀態(tài)。如果否,在狀態(tài)504處生成句法錯(cuò)誤,它將被包含在由靜態(tài)源代碼分析器產(chǎn)生的出錯(cuò)報(bào)告中。另一方面,如果句法正確,或一旦在狀態(tài)504處生成句法錯(cuò)誤,那么狀態(tài)對(duì)象500前進(jìn)至狀態(tài)506。
在狀態(tài)506處,確定是否滿足API的依賴性條件。如果否,那么在狀態(tài)508處,生成包含在由靜態(tài)源代碼分析器產(chǎn)生的出錯(cuò)報(bào)告中的依賴性錯(cuò)誤。例如,如在API文檔中指定如果僅在調(diào)用另一API之后或必須執(zhí)行某些其它函數(shù)之后調(diào)用API,那么可能存在依賴性錯(cuò)誤。可以包含多個(gè)依賴性檢查狀態(tài)506,其中每一個(gè)都評(píng)估一特定的依賴性。如果滿足依賴性或在狀態(tài)508處生成依賴性錯(cuò)誤,那么狀態(tài)對(duì)象500前進(jìn)至狀態(tài)510。
在狀態(tài)510處,確定第一變量是否大于零。如果否,那么在狀態(tài)512處,不將第二變量標(biāo)記為已被初始化或已被處理。另一方面,如果在狀態(tài)510處確定第一變量大于零,那么在狀態(tài)514處,第二變量被標(biāo)記為已被初始化或已被處理。
狀態(tài)對(duì)象500協(xié)同由靜態(tài)源代碼分析器使用的其它狀態(tài)對(duì)象一起操作。因此,例如,當(dāng)定義了x時(shí),由靜態(tài)源代碼分析器為其創(chuàng)建狀態(tài)對(duì)象。因?yàn)閤還沒有被初始化,其狀態(tài)對(duì)象指示它還沒有被初始化。在沒有對(duì)API功能的某些理解的情況下,靜態(tài)源代碼分析器可能假定API或者從未初始化[out]變量,從而導(dǎo)致假肯定,或者總是初始化[out]變量,從而忽略潛在的問題。因此,本發(fā)明中對(duì)API的建模確保向用戶提供更好且更準(zhǔn)確的信息。
調(diào)用示例性API的代碼的靜態(tài)源代碼分析一方面,不是如圖6A所示的對(duì)API進(jìn)行建模的靜態(tài)源代碼分析器600可以假定,除非如所示x是由源代碼610初始化的(源代碼610不包括API源代碼),否則x沒有被初始化。因此,不考慮API調(diào)用620可能初始化x(當(dāng)z大于零)的概率,第11行的表達(dá)式y(tǒng)=1/x將導(dǎo)致出錯(cuò)消息640a,因?yàn)槿绻麤]有初始化x,它將導(dǎo)致除以未定義的值。圖6A的出錯(cuò)消息640a最終結(jié)果是準(zhǔn)確的語句,因?yàn)樵诒磉_(dá)式650a中將變量z置為零且因?yàn)閦不大于零將不初始化x,從而API沒有初始化x。然而,出錯(cuò)消息640為準(zhǔn)確的純粹是偶然的,因?yàn)槌R?guī)靜態(tài)源代碼分析器不適用于評(píng)估API的功能,因此不能確定API是否初始化了x。
然而,如圖6B所示,在沒有API模型的好處的情況下,靜態(tài)源代碼分析器600a即使在x初始化時(shí)也將生成類似同樣的出錯(cuò)消息。圖6B中,靜態(tài)源代碼分析器600分析除語句650a(圖6A)的改變以外與源代碼610完全相同的源代碼610′,在650a中初始化z并將其置為等于零,而在API調(diào)用620之前的語句650b中,初始化z并將置為等于一。從而,如上所述,因?yàn)閦被初始化且大于零,API將執(zhí)行x上的函數(shù)并將x返回為某個(gè)非零數(shù)字。從而,表達(dá)式630不導(dǎo)致除以未初始化的變量。盡管如此,仍舊生成指示除以未初始化變量的問題的出錯(cuò)消息640b,因?yàn)樵创a分析器600不能確定語句650b使得API調(diào)用620返回有效且不為零的值x。出錯(cuò)消息640b構(gòu)成明顯不正確的假肯定,因?yàn)楸磉_(dá)式630不導(dǎo)致除以未定義、未初始化的值。
圖6A或圖6B的結(jié)果都是不可接受的。出錯(cuò)消息640a呈現(xiàn)了可能不為真的語句,而軟件開發(fā)員可能難以試圖調(diào)試代碼來標(biāo)識(shí)及可能更正引起靜態(tài)源代碼分析器600a生成該消息的問題。由靜態(tài)源代碼分析器生成的出錯(cuò)消息640b也是不可接受的,因?yàn)樗诓淮嬖阱e(cuò)誤的地方指示了錯(cuò)誤;軟件開發(fā)員不太可能修改代碼以便阻止該消息;從而,軟件開發(fā)員必須忽略出錯(cuò)消息640b。
或者,如圖7A中所示,靜態(tài)源代碼分析器700被配置成在假定在源代碼610′中初始化了傳遞給諸如API調(diào)用620中調(diào)用的外部函數(shù)等外部函數(shù)的參數(shù)的情況下操作。作出該假設(shè),靜態(tài)源代碼分析器700不將第11行的表達(dá)式630,y=1/x視為可能會(huì)引起錯(cuò)誤。因此,靜態(tài)源代碼分析器700生成指示沒有檢測到錯(cuò)誤的消息740a。偶然地,消息740a是正確的,因?yàn)楸磉_(dá)式650b初始化了z并將其置為等于一,導(dǎo)致API初始化并返回x的非零值。
然而,在沒有將靜態(tài)源代碼分析器700配置成分析API的情況下,該假設(shè)可能是錯(cuò)誤的。如圖7B中所示,靜態(tài)源代碼分析器700分析源代碼610,其中在語句650a中初始化變量z,并將其置為零,所作假設(shè)是錯(cuò)誤的。因?yàn)閦被初始化為零,那么在源代碼600中,API調(diào)用620不初始化x。因此,表達(dá)式導(dǎo)致除以未定義的值。然而,消息740b指示沒有發(fā)現(xiàn)錯(cuò)誤。因此,靜態(tài)源代碼分析器沒有被配置成對(duì)API建模,再一次生成不準(zhǔn)確的消息740b。再次,靜態(tài)源代碼分析器700生成可能是假肯定或可能無法包括實(shí)際錯(cuò)誤的消息。
相反,使用其中靜態(tài)源代碼分析器對(duì)API建模的本發(fā)明的實(shí)施例,可以避免上述問題。如圖8A中所示,靜態(tài)源代碼分析器800分析其中由語句650a初始化變量z并將其置為等于零的源代碼610。作為結(jié)果,API調(diào)用620導(dǎo)致沒有初始化變量x,導(dǎo)致表達(dá)式630中除以未定義的值。因?yàn)殪o態(tài)源代碼分析器800包括使用API原語的API模型,靜態(tài)源代碼分析器正確地對(duì)API的功能建模,靜態(tài)源代碼分析器識(shí)別非法函數(shù)并生成準(zhǔn)確的出錯(cuò)消息840a。
而且,如圖8B中所示,當(dāng)靜態(tài)源代碼分析器800分析包括在API調(diào)用620之前將z初始化為1的表達(dá)式650b的源代碼610′時(shí),API將返回x的非零值,且表達(dá)式630也不表示非法操作。因?yàn)殪o態(tài)源代碼分析器800使用如前所述的API原語對(duì)API的功能建模,靜態(tài)源代碼分析器正確地確定表達(dá)式650中對(duì)z的初始化初始化了x并返回非零值,所以它返回指示沒有發(fā)現(xiàn)錯(cuò)誤的消息840b。因此,在源代碼610和610′的情況下,靜態(tài)源代碼分析器800均生成準(zhǔn)確的報(bào)告,它標(biāo)識(shí)真正的錯(cuò)誤,但不包括假肯定。
使用API模型的靜態(tài)源代碼分析的處理圖9是示出根據(jù)本發(fā)明的實(shí)施例,用于分析源代碼的邏輯步驟的流程圖900。在步驟902處開始分析。在步驟904處,接收源代碼。在步驟906處,標(biāo)記或忽略注釋及其它非程序設(shè)計(jì)指令的內(nèi)容。在步驟908處,模擬源代碼元素。在判斷步驟910處,確定源代碼元素是否標(biāo)識(shí)非標(biāo)準(zhǔn)元素,諸如API調(diào)用或其它外部函數(shù)調(diào)用。如果元素被標(biāo)識(shí)為非標(biāo)準(zhǔn)元素,那么在判斷步驟912處,確定該非標(biāo)準(zhǔn)元素是否表示API調(diào)用。如果否,那么在步驟914處,生成消息“未識(shí)別的表達(dá)式”。另一方面,如果在判斷步驟912處確定該非標(biāo)準(zhǔn)元素是API調(diào)用,那么在步驟916處,確定是否存在對(duì)該API的分析模型。如果否,那么在步驟918處,生成指示對(duì)該API沒有模型可用的出錯(cuò)消息。
另一方面,如果在判斷步驟916處確定API模型可用,或者之前在判斷步驟910處確定源代碼元素為標(biāo)準(zhǔn)源代碼元素,那么在步驟920處,確定在源代碼元素中是否檢測到錯(cuò)誤。如果是,那么在步驟922處生成適當(dāng)?shù)某鲥e(cuò)消息。另一方面,如果在判斷步驟920處沒有檢測到錯(cuò)誤,或者一旦在914、908或922處生成適當(dāng)?shù)南?,流程圖900前進(jìn)至判斷步驟924處。在判斷步驟924處,確定是否模擬了所有源代碼元素。如果否,那么在步驟926處,標(biāo)識(shí)要被評(píng)估的下一源代碼元素,且在步驟908處評(píng)估下一源代碼元素?;蛘?,一旦在步驟924處確定已經(jīng)模擬了所有源代碼元素,那么生成包含在之前步驟中生成的所有出錯(cuò)消息的報(bào)告。在步驟930處結(jié)束靜態(tài)源代碼分析。
盡管結(jié)合實(shí)現(xiàn)本發(fā)明的較佳形式及其修改來描述了本發(fā)明,但是本領(lǐng)域的普通技術(shù)人員可以理解,可以對(duì)本發(fā)明進(jìn)行所附權(quán)利要求書范圍內(nèi)的眾多其它修改。從而,本發(fā)明的范圍不旨在由以上描述以任何方式限制,而是完全參考所附權(quán)利要求書來確定。
權(quán)利要求
1.一種用于分析其函數(shù)源代碼實(shí)現(xiàn)不可用的外部函數(shù)的調(diào)用的方法,包括以下步驟(a)標(biāo)識(shí)由源代碼對(duì)所述外部函數(shù)的不恰當(dāng)調(diào)用導(dǎo)致的至少一個(gè)潛在錯(cuò)誤;(b)標(biāo)識(shí)將導(dǎo)致所述潛在錯(cuò)誤的至少一個(gè)條件;(c)創(chuàng)建函數(shù)的模型以測試導(dǎo)致潛在錯(cuò)誤并當(dāng)發(fā)現(xiàn)所述條件時(shí)將觸發(fā)生成出錯(cuò)消息的所述至少一個(gè)條件;以及(d)將所述模型與源代碼分析器相關(guān)聯(lián),使得當(dāng)所述源代碼由所述源代碼分析器分析時(shí),所述模型被應(yīng)用來評(píng)估對(duì)所述外部函數(shù)的調(diào)用。
2.如權(quán)利要求1所述的方法,其特征在于,所述外部函數(shù)包括應(yīng)用程序編程接口。
3.如權(quán)利要求1所述的方法,其特征在于,還包括基于實(shí)現(xiàn)所述外部函數(shù)的要求,標(biāo)識(shí)將導(dǎo)致所述潛在錯(cuò)誤的至少一個(gè)條件的步驟。
4.如權(quán)利要求1所述的方法,其特征在于,所述至少一個(gè)條件包括以下的至少其中之一(a)所述應(yīng)用程序編程接口可接受的輸入?yún)?shù)的不正確輸入類型;(b)所述應(yīng)用程序編程接口可接受的輸入?yún)?shù)的不正確輸入內(nèi)容范圍;(c)可由所述應(yīng)用程序編程接口生成的輸出參數(shù)的不正確輸出類型;(d)可由所述應(yīng)用程序編程接口生成的輸出參數(shù)的不正確輸出內(nèi)容范圍;(e)不能調(diào)用在調(diào)用所述外部函數(shù)之前必須被調(diào)用的先決函數(shù);以及(f)不能調(diào)用在調(diào)用所述外部函數(shù)之后必須被調(diào)用的后決函數(shù)。
5.如權(quán)利要求1所述的方法,其特征在于,所述模型是使用可用于測試導(dǎo)致潛在錯(cuò)誤的所述至少一個(gè)條件的多個(gè)原語來創(chuàng)建的。
6.如權(quán)利要求5所述的方法,其特征在于,所述源代碼分析器包括被配置成存儲(chǔ)所述創(chuàng)建的模型的模型儲(chǔ)存庫,使得所述源代碼分析器能夠在評(píng)估源代碼及標(biāo)識(shí)對(duì)所述外部函數(shù)的引用之后訪問所述模型。
7.一種含有用于執(zhí)行如權(quán)利要求1所述的步驟的機(jī)器可執(zhí)行指令的存儲(chǔ)器介質(zhì)。
8.一種用于使源代碼分析器適用于評(píng)估其函數(shù)源代碼實(shí)現(xiàn)不可用的外部函數(shù)的方法,包括以下步驟(a)使所述源代碼分析器適用于識(shí)別及分析所述外部函數(shù);(b)標(biāo)識(shí)由源代碼對(duì)所述外部函數(shù)的不恰當(dāng)調(diào)用導(dǎo)致的至少一個(gè)潛在錯(cuò)誤;(c)標(biāo)識(shí)將導(dǎo)致所述潛在錯(cuò)誤的至少一個(gè)條件;(d)創(chuàng)建所述函數(shù)的模型以測試導(dǎo)致潛在錯(cuò)誤并當(dāng)發(fā)現(xiàn)所述條件時(shí)將觸發(fā)生成出錯(cuò)消息的所述至少一個(gè)條件;(e)將所述模型包含在源代碼分析器內(nèi),使得當(dāng)所述源代碼由所述源代碼分析器分析時(shí),所述模型被應(yīng)用來評(píng)估對(duì)所述外部函數(shù)的調(diào)用;以及(f)在當(dāng)分析所述源代碼時(shí)由所述源代碼分析器生成的出錯(cuò)報(bào)告中包含由所述模型觸發(fā)的出錯(cuò)消息。
9.如權(quán)利要求8所述的方法,其特征在于,所述外部函數(shù)包括應(yīng)用程序編程接口。
10.如權(quán)利要求8所述的方法,其特征在于,還包括基于實(shí)現(xiàn)所述外部函數(shù)的要求,標(biāo)識(shí)將導(dǎo)致潛在錯(cuò)誤的所述至少一個(gè)條件的步驟。
11.如權(quán)利要求8所述的方法,其特征在于,所述至少一個(gè)條件包括以下的至少其中之一(a)所述應(yīng)用程序編程接口可接受的輸入?yún)?shù)的不正確輸入類型;(b)所述應(yīng)用程序編程接口可接受的輸入?yún)?shù)的不正確輸入內(nèi)容范圍;(c)可由所述應(yīng)用程序編程接口生成的輸出參數(shù)的不正確輸出類型;(d)可由所述應(yīng)用程序編程接口生成的輸出參數(shù)的不正確輸出內(nèi)容范圍;(e)不能調(diào)用在調(diào)用所述外部函數(shù)之前必須被調(diào)用的先決函數(shù);以及(f)不能調(diào)用在調(diào)用所述外部函數(shù)之后必須被調(diào)用的后決函數(shù)。
12.如權(quán)利要求8所述的方法,其特征在于,所述模型是使用可用于測試導(dǎo)致潛在錯(cuò)誤的所述至少一個(gè)條件的多個(gè)原語來創(chuàng)建的。
13.如權(quán)利要求12所述的方法,其特征在于,所述源代碼分析器包括被配置成存儲(chǔ)所創(chuàng)建的模型的模型儲(chǔ)存庫,使得所述源代碼分析器能夠在評(píng)估源代碼及標(biāo)識(shí)對(duì)所述外部函數(shù)的引用之后訪問所述模型。
14.如權(quán)利要求8所述的方法,其特征在于,還包括使所述源代碼分析器適用于評(píng)估為選取的計(jì)算環(huán)境所提供的軟件開發(fā)工具包中所包含的二進(jìn)制庫中含有的多個(gè)外部函數(shù)的步驟。
15.一種含有用于執(zhí)行如權(quán)利要求8所述的步驟的機(jī)器可執(zhí)行指令的存儲(chǔ)器介質(zhì)。
16.一種用于分析對(duì)其函數(shù)源代碼實(shí)現(xiàn)不可用的外部函數(shù)的調(diào)用的系統(tǒng),所述系統(tǒng)包括(a)至少一個(gè)用戶輸入設(shè)備;(b)顯示器;(c)與所述輸入設(shè)備和顯示器通信的處理器;以及(d)與所述處理器通信的存儲(chǔ)器,所述存儲(chǔ)器存儲(chǔ)使得所述處理器實(shí)現(xiàn)多個(gè)功能的數(shù)據(jù)和機(jī)器指令,所述功能包括(i)標(biāo)識(shí)由源代碼對(duì)所述外部函數(shù)的不恰當(dāng)調(diào)用導(dǎo)致的至少一個(gè)潛在錯(cuò)誤;(ii)標(biāo)識(shí)將導(dǎo)致所述潛在錯(cuò)誤的至少一個(gè)條件;(iii)創(chuàng)建函數(shù)的模型以測試導(dǎo)致潛在錯(cuò)誤并當(dāng)發(fā)現(xiàn)所述條件時(shí)將觸發(fā)生成出錯(cuò)消息的所述至少一個(gè)條件;以及(iv)將所述模型與源代碼分析器相關(guān)聯(lián),使得當(dāng)所述源代碼由所述源代碼分析器分析時(shí),所述模型被應(yīng)用來評(píng)估對(duì)所述外部函數(shù)的調(diào)用。
17.如權(quán)利要求16所述的系統(tǒng),其特征在于,所述外部函數(shù)包括應(yīng)用程序編程接口。
18.如權(quán)利要求16所述的系統(tǒng),其特征在于,所述機(jī)器指令還引起所述處理器基于實(shí)現(xiàn)所述外部函數(shù)的要求,標(biāo)識(shí)將導(dǎo)致潛在錯(cuò)誤的所述至少一個(gè)條件。
19.如權(quán)利要求16所述的系統(tǒng),其特征在于,所述至少一個(gè)條件包括以下的至少其中之一(a)所述應(yīng)用程序編程接口可接受的輸入?yún)?shù)的不正確輸入類型;(b)所述應(yīng)用程序編程接口可接受的輸入?yún)?shù)的不正確輸入內(nèi)容范圍;(c)可由所述應(yīng)用程序編程接口生成的輸出參數(shù)的不正確輸出類型;(d)可由所述應(yīng)用程序編程接口生成的輸出參數(shù)的不正確輸出內(nèi)容范圍;(e)不能調(diào)用在調(diào)用所述外部函數(shù)之前必須被調(diào)用的先決函數(shù);以及(f)不能調(diào)用在調(diào)用所述外部函數(shù)之后必須被調(diào)用的后決函數(shù)。
20.如權(quán)利要求16所述的系統(tǒng),其特征在于,所述模型是使用可用于測試導(dǎo)致潛在錯(cuò)誤的所述至少一個(gè)條件的多個(gè)原語來創(chuàng)建的。
全文摘要
在處理諸如應(yīng)用程序編程接口(API)等源代碼不可用的外部函數(shù)中,使用模型來評(píng)估是否恰當(dāng)?shù)卣{(diào)用了該外部函數(shù)。標(biāo)識(shí)由對(duì)外部函數(shù)的不恰當(dāng)調(diào)用潛在導(dǎo)致的錯(cuò)誤以及將導(dǎo)致該潛在錯(cuò)誤的至少一個(gè)條件。創(chuàng)建模型來測試將該導(dǎo)致潛在錯(cuò)誤的條件。當(dāng)發(fā)現(xiàn)條件時(shí),觸發(fā)生成出錯(cuò)消息。模型與源代碼分析器相關(guān)聯(lián),使得當(dāng)由源代碼分析器分析源代碼時(shí),模型被應(yīng)用來評(píng)估對(duì)外部函數(shù)的調(diào)用??梢詮拿枋鐾獠亢瘮?shù)或API的操作的文檔中獲取潛在的錯(cuò)誤及導(dǎo)致錯(cuò)誤的條件,諸如輸入/輸出參數(shù)錯(cuò)誤或依賴性錯(cuò)誤。
文檔編號(hào)G06F9/44GK1825278SQ20061000597
公開日2006年8月30日 申請日期2006年1月20日 優(yōu)先權(quán)日2005年2月22日
發(fā)明者M·E·朱伯蘭 申請人:微軟公司