源代码静态分析模拟器的自定义api建模的制作方法

文档序号:6554450阅读:213来源:国知局
专利名称:源代码静态分析模拟器的自定义api建模的制作方法
技术领域
本发明一般涉及计算机软件开发,尤其涉及用于改进计算机源代码的评估来检测编程错误的方法和系统。
背景技术
过去几十年中,微处理器、随机存储存储器(RAM)和存储系统的日益改进的性价比影响了如何开发计算机软件。过去,在硬件资源更昂贵的时候,通常以汇编语言编写源代码。以低级语言编写代码对开发员而言是较耗时的,但是结果得到更有效和紧凑的代码。然而,作为处理器、存储器和存储的日益改进的性价比的结果,更多的程序设计是以诸如C/C++、Visual Basic等高级语言执行的,来最小化软件开发的成本。
已经为软件开发员创建了更好的工具,这些工具使得软件创建更有效和多产,并进一步利用可用的改进计算系统。例如,静态源代码分析工具帮助软件开发员通过推断源代码的可能行为来标识错误。某些静态源代码分析工具编译代码来标识常规编译器可能无法检测到的导致违背程序设计语言规则的句法缺陷。某些静态源代码分析工具不包括编译器,但是相反,截取外部编译器的输出,解析经编译的代码并分析它。一旦静态源代码分析工具评估了源代码以找出可能的句法错误之后,由代码分析器生成的源代码的表示还允许模拟器评估代码以找出语义问题。因此,静态源代码分析工具帮助检测编译器可能没有检测到的句法错误,以及编译器不能检测的语义错误。
图1A示出了常规(现有技术)静态源代码分析器100a的框图。由软件开发员准备的源代码102a是静态源代码分析器100a的输入。源代码首先由输入处理器104a解析,它忽略头部块和注释,将源代码精简为提交给模拟器108a的标准程序设计指令106a的列表。模拟器108标识源代码中的句法和语义错误。例如,误用、拼错或不含有适当的参数或定界符的表达式被标识为句法错误。另外,模拟器108a标识除文字或句法之外的错误。例如,如果源代码访问不能被适当地启动的存储器,那么模拟器108a标识该错误。又例如,如果源代码请求初始化变量,且变量在某个界限内,但是该变量没有被初始化或者由于该变量的值超出预定的界限而无效,那么模拟器108a也标识错误。由模拟器108a标识的错误在可由软件开发员用来修改和修复其源代码的错误报告110a中呈现。
图1B示出了来自现有的源代码分析器的示例性屏幕120。在该源代码分析器中,在源代码窗口124中可查看被提交以供分析的源代码122,而在分析窗口128中呈现出错消息126。出错消息126包括与源代码122中的行132的相关性130以协助软件开发员更正错误。
静态源代码分析器对软件开发员非常有帮助,因为它们协助软件开发员标识可能干扰源代码的编译,或者即使源代码平安无事地编译了,仍旧可能使得软件在操作过程中失败的问题。静态源代码分析器不代替测试来确定所得到的软件是否按照预期的方式工作。然而,通过向开发员呈现包含与源代码122中的特定行132的相关性的出错消息126,静态源代码分析器允许开发员快速地定位其源代码中的潜在的句法和语义问题。
静态源代码分析器的准确性取决于它们解释所呈现的源代码的能力。作为结构,可能遗漏源代码中的某些错误。另外,如果静态源代码分析器不正确地解释了正被分析的源代码,那么当被评估的源代码是正确的时候可能会生成假肯定。不幸的是,假肯定的出现累计为使得指示源代码中实际错误的出错消息变得模糊的噪声。结果是,被分析的软件代码中的实际错误可能被软件开发员忽略。
对软件开发员很有帮助的其它工具是软件开发员工具包。软件开发员工具包一般是为诸如Microsoft WINDOWSTM等特定操作系统,或诸如Microsoft XBOXTM等计算或游戏平台创建的,以通过允许对之前创建的软件工具的访问而使软件开发变得更容易。这些软件开发包可以包括执行可能被开发员包含在其代码中的公共函数的预写例程的源代码。通过提供对这样的软件例程的方便的访问,开发员不必浪费时间来重新编写已经创建的公共例程。
软件开发工具包也可以包括可在开发员为其创建软件的操作系统中访问的应用程序接口或应用程序编程接口(API)。API可以被用来调用服务以生成图形、生成声音和任何数量的其它功能。另外,调用不同地实现但功能可比的服务的API可以用来提供可为其编译源代码的不同平台之间的源代码可移植性。可能最重要的是,API可用于提供高级语言源代码和与操作环境的硬件设备更直接操作的较低级实用程序之间的接口。
在二进制代码库的集合中,API通常离散分布,或者作为软件开发工具包的一部分。一般,用于创建API的源代码不是分布的,或以其它方式使其对开发员可用。源代码不可用于保护操作环境的开发员的各种私人考虑。然而,即使API的源代码实现不可用,使用解释API操作、调用API的正确句法、传递给API的参数和由API返回的值的特征的软件开发工具包,文档或其它信息仍可以是可用的。
不幸的是,向静态源代码分析器提交调用一个或多个API的源代码可能导致生成多个错误。如上所述,源代码分析器仅在它被配置成理解源代码的情况下才是准确的。因此,静态源代码分析器可能无法分析API签名,因为仅向源代码分析器提供API签名,而源代码分析器不能访问API的源代码实现。
如在图1C的现有示例中示出,当分析源代码102c时,静态源代码分析器100c的输入处理器104c将API签名152识别为与标准程序设计指令106c不同。API签名152可被认为是出错报告110c中的句法错误,因为API签名表示了非标准的表达式。或者,例如在C++中,可以向API签名152追加“extern”指定,它将阻止模拟器108c试图评估API签名152的语义。无需API的源代码实现,静态源代码分析器就能够通过根据API签名确定是否向API传递适当的参数来评估API调用的句法。然而,在没有源代码的情况下,静态源代码分析器不能在语义上评估API签名152、它们的行为及它们对调用API签名152的源代码的效果。在遇到“extern”指定之后,静态源代码分析器不试图在语义上评估随后的表达式。
在不访问API的源代码实现的情况下,静态源代码分析器不能确定API可能具有的效果,例如在传递给API的参数上的效果。结果是,当一带有变量的问题实际关于该API时,静态源代码分析器108c可能生成关于该问题的出错消息。结果是,源代码中的API的内容可能导致大量的假肯定出错消息,即由源代码分析器生成的噪声,不幸的是,这可能将注意力从实际的真正出错消息移开。另外,因为源代码分析器可能无法评估API调用或其效果,所以源代码分析器可能无法检测由这样的API调用导致的错误。API可以在传递给它的参数上执行操作,该操作将导致源代码中某个后继点处的非法操作。因此,如果源代码分析器不能够评估API的操作,那么源代码分析器可能无法检测到源代码中的相关错误。
从而,期望提供即使不必访问API的源代码实现也能够评估API调用的方法和系统。

发明内容
从而,本发明的一个优点是,它提供了用于即使在外部函数调用的源代码实现不可用的情况下,也能评估诸如API调用等外部函数调用的方法和系统。通常,已知的源代码分析器忽略外部函数调用,且作为结果,可能错过外部函数调用中的错误,或者当实际上检测到的错误由外部函数调用解决时标记假肯定。因为外部函数的源代码不可用,不能将函数源代码本身包含在源代码中并对其分析。然而,因为函数源代码不可用,外部函数的提供者可能提供描述外部函数操作的文档或其它信息。该文档使得软件开发员能够理解向该外部函数传递什么参数、该外部函数输出什么参数、API取决于什么先决函数、以及其它重要的信息。从该描述性的信息中,可以开发模型来确保恰当地调用了API。根据本发明的一个实施例,伴随静态源代码分析器所包含的一组原语向用户提供了对API功能建模的方式,使得源代码分析器能够评估API调用的行为和效果。
因此,本发明的一个方面针对用于分析函数源代码实现不可用的外部函数的调用的方法。标识由源代码对外部函数的不恰当调用导致的至少一个潜在错误,并标识将导致该潜在错误的至少一个条件。使用了可用于测试导致潜在错误的至少一个条件,且当发现条件时能够启动生成出错消息的外部函数的模型。该模型与源代码分析器相关联,使得当由源代码分析器分析源代码时,该模型被应用来评估外部函数的调用或操作。
外部函数可以包括API。基于描述外部函数的操作的信息来对可能导致潜在错误的至少一个条件进行标识。条件可以包括应用程序编程接口可接受的输入参数的不正确输入类型,或者API可接受的输入参数的不正确输入内容范围。类似地,条件可以包括可由API生成的输出参数的不正确输出,或可由API生成的输出参数的不正确输出内容范围。条件也可以包括不能调用在调用外部函数之前必须被调用的先决函数,或不能调用在调用外部函数之后必须被调用的后决函数。
可以使用可用于测试导致潜在错误的至少一个条件的多个原语来创建模型。源代码分析器包括被配置成存储所创建的模型的模型储存库,使得源代码分析器能够在评估源代码并标识对外部函数的引用之后访问该模型。


当结合附图参考以下详细描述时,可以更容易且更好地领会和理解本发明的前述方面和众多附加优点,附图中图1A(现有技术)是典型的静态源代码分析器的功能框图;
图1B(现有技术)是来自典型的静态源代码分析器的屏幕;图1C(现有技术)是面对API签名的典型的静态源代码分析器的功能框图;图2是适用于使用本发明的一个实施例的计算设备或个人计算机(PC)的功能框图;图3是使用本发明的一个实施例来评估API签名的静态源代码分析器的功能框图;图4是示出用于为静态源代码分析器创建API模型的逻辑步骤的流程图;图5是对从API的功能的描述中导出的API功能建模的状态对象的状态图;图6A和6B(现有技术)是来自在假定传递给API的参数不是由该API的初始化的情况下配置的静态源代码分析器的屏幕;图7A和7B(现有技术)是来自假定传递给API的参数是由该API的初始化的情况下配置的静态源代码分析器的屏幕;图8A和8B是来自使用本发明的一个实施例来对API的功能建模的静态源代码分析器的屏幕;以及图9是示出根据本发明的一个实施例,用于分析源代码的逻辑步骤的流程图。
具体实施例方式
用于实现本发明的示例性计算系统参考图2,示出了适用于本发明的实施例的示例性常规计算系统。该系统包括形式为PC 220a的通用计算设备,PC 220a装备有处理单元221、系统存储器222和系统总线223。系统总线将包括系统存储器在内的各种系统组件耦合至处理单元221,且可以是若干类型的总线结构中的任一种,包括存储器总线或存储器控制器、外围总线和使用各种总线体系结构中的任一种的局部总线。系统存储器包括只读存储器(ROM)224和随机存取存储器(RAM)225。基本输入/输出系统(BIOS)226包含有助于诸如启动时PC 220中元件之间传递信息的基本例程,它通常存储在ROM 224中。PC 220还可以包括用于从硬盘(未示出)中读取或向其写入的硬盘驱动器227,用于从可移动磁盘229中读取或向其写入的磁盘驱动器228,以及用于从诸如光盘只读存储器(CD ROM)或其它光学介质等可移动光盘231中读取或向其写入的光盘驱动器230。硬盘驱动器227、磁盘驱动器228和光盘驱动器230分别由硬盘驱动器接口232、磁盘驱动器接口233和光盘驱动器接口234连接至系统总线223。驱动器及其相关联的计算机可读介质为PC 220提供了对计算机可读机器指令、数据结构、程序模块和其它数据的非易失性存储。尽管此处所述的示例性环境使用硬盘、可移动磁盘229和可移动光盘231,但是本领域的其它技术人员可以理解,也可以在示例性操作环境中使用用于存储可由计算机访问的数据和机器指令的其它类型的计算机可读介质,诸如盒式磁带、闪存卡、数字多功能盘(DVD)、贝努利盒式磁盘、RAM、ROM等。
可以在硬盘、磁盘229、光盘231、ROM 224或RAM 225上存储包括操作系统235、一个或多个应用程序模块236、其它程序模块237和程序数据238的多个程序模块。用户可以通过诸如经由I/O设备接口246与系统总线223通信的键盘240和定点设备242向PC 220输入命令和信息并提供控制输入。定点设备242可以包括鼠标、指示笔、无线遥控器、或其它指示器,但是关于本发明,可以省略这样的常规定点设备,因为用户可以使用交互显示用于输入和控制。如在下文中所使用的,术语“鼠标”旨在包含可用于控制屏幕上光标位置的基本上任何定点设备。一个或多个音频输入/输出设备243,包括耳机、扬声器和麦克风,也经由I/O设备接口246加入个人计算机220。其它输入设备(未示出)可以包括操纵杆、触觉操纵杆、偏转系统、脚踏板、游戏垫、圆盘式卫星天线、扫描仪等。这些和其它输入/输出(I/O)设备通常由耦合至系统总线223的I/O接口246连接至处理单元221。术语I/O接口旨在包含专供串行端口、并行端口、游戏端口、键盘端口和/或通用串行总线(USB)使用的每一接口。监视器247经由诸如视频适配器248等合适的接口连接至系统总线223。可以理解,PC通常耦合至其它外围输出设备(未示出),诸如扬声器(经由声卡或其它音频接口(未示出))和打印机。
PC 220可使用至一台或多台远程计算机,诸如远程计算机249的逻辑连接在网络化环境中操作。远程计算机249可以是另一台PC、服务器(通常一般被配置成与PC 220a非常类似)、路由器、网络PC、对等设备、卫星或其它常见网络节点,且通常包括上文相对于PC 220a描述的许多或所有元件,尽管在图2中只示出外部存储器存储设备250。图2中所示逻辑连接包括局域网(LAN)251和广域网(WAN)252。这样的网络环境在办公室、企业范围计算机网络、内联网和因特网中是常见的。
当在LAN网络环境中使用时,PC 220通过网络接口或适配器253连接至局域网251。当在WAN网络环境中使用时,PC 220通常包括调制解调器254或用于通过诸如因特网的WAN 252建立通信的其它装置,诸如线缆调制解调器、数字用户线路(DSL)接口、或综合业务数字网络(ISDN)接口。调制解调器254可以是内置或外置的,它通过I/O设备接口246(即,通过串行端口)连接至或耦合至系统总线223。在网络化环境中,由PC 220使用的程序模块或其部分可以存储在远程存储器存储设备中。可以理解,所示的网络连接是示例性的,且可以使用在计算机之间建立通信链路的其它手段,诸如无线通信和宽频网络链路。
适用于评估API的源代码分析器图3示出了静态源代码分析器300的框图,它包括如上结合图1A和1C所述的常规静态源代码分析器的某些属性。由软件开发员准备源代码302,并将其提交给静态源代码分析器300以检测潜在的错误。源代码由输入处理器304解析。输入处理器忽略注释、头部块、带有“extern(外部)”或类似句法前缀的行等,从而表示由模拟器308分析的标准程序设计指令306。另外,可以由处理器304识别一个或多个外部函数调用或API签名352。在随后的描述中,调用的外部函数被描述为API。尽管如此,本发明的实施例可用于评估可能由其源代码对静态源代码分析不可用的其它外部函数调用的不正确调用或操作引起的错误。
如上所述,照常规,向API签名的声明追加指定“extern”或类似的标识符指示,表示API的表达式调用源代码实现不可用的外部例程。如在本领域中可以理解,“extern”指定传递至编译器,而不试图解决该外部例程的任何后继调用。链接程序将负责定位所调用的函数的目标代码,以及编译之后在二进制代码级上解决该外部函数的代码实现。另外,“extern”指定传递至常规静态源代码分析器,而不试图在语义上分析该被指定的外部函数。尽管如此,静态源代码分析器仍旧可以评估后继外部函数调用的句法,以确保外部函数的调用符合指定的函数的句法。
根据本发明的各实施例,所标识的潜在的API签名352被提交给API模拟器360。API模拟器360评估潜在的API签名352,以确定句法是否正确,是否向API传递了恰当的参数,传递的参数是否是适当类型的,并以其它方式评估API签名352是否存在编码错误。由API模拟器360向模拟器308传递对API签名352是否是正确形式的判断。使用由API模拟器360提供的信息,模拟器308在出错报告310中生成包含错误的API签名352的出错消息。相反,可能被模拟器308标记为错误的假肯定由于其缺乏与API签名352的熟悉性,在出错报告310中不被报告为错误。
可以理解,如果API的源代码实现对软件开发员可用,那么软件开发员可以在软件开发员的源代码302中合并API源代码实现,以及源代码302的其余部分,以供模拟器308评估。然而,如上所述,一般而言,在使得API能够与从源代码302编译而来的其它目标代码模块链接的二进制代码库中,仅以其目标代码形式提供API。有利的是,本发明的实施例不需API的提供者供应API的源代码实现。
而是相反,对所构想、预期或期望与源代码302一起使用的每一API签名,API模拟器360包括对每一API签名的评估的模型。例如,可以为标识为最有可能调用的一组API开发模型。结果是,可以清除由于假肯定而可能被包含在出错报告310中的大多数噪声,而不必包含可能被调用的每个API的模型。
API模拟器360包括源自较佳地由API开发员在对软件开发员可用的SDK和/或API文档380中提供的信息的模型。一般而言,SDK/API文档380描述API的功能、指示要向API提供的参数,API所需或所用的值的形式、以及API的其它功能特征。SDK/API文档380用于使用API原语370对API建模。API原语370包括打包在与可由用户用来对API的功能建模的模拟器相关联的建模库中的一组例程,使得API模拟器360可以评估由源代码调用的API的效果。以下进一步描述API原语370的使用。
因此,通过使用API原语370及审阅SDK/API文档380,即使不访问API源代码,也可以推出某些规则来评估可能被包含在提交给静态源代码分析器300的源代码302中的API签名352的调用和/或操作。这些规则可以被包含在API模拟器360中,且可以被应用于所标识的潜在API签名352。然后评估所标识的API签名,来确定它们是否使用了适当的句法、向API传递了适当的参数、及是否在其它方面遵循API的规则,以评估源代码302中的API签名是否有效。如果API模拟器360被应用来确定在源代码中标识的API签名352是否被正确地实现,那么在出错报告310中将不报告任何出错消息。另一方面,如果在源代码302中存在调用API的错误,那么API模拟器360将该出错消息传达给模拟器308。因此,模拟器308可以在出错报告310中包括关于在源代码302中标识的API签名的适当的出错消息。
较佳地,API模拟器360不仅评估API指示的独立的句法和签名的结构,而且也被配置成向模拟器308传递包含在源代码302中的API签名是否解决由模拟器308检测到的源代码302中的其它潜在错误。作为一个简单的示例,API可以评估传递给API的参数,并对其值超过可接受值的某个限制的部分进行截断或舍入。从而,如果模拟器308检测到特定值超出界限,则基于源代码302,模拟器308可以查询API模拟器360来确定API是否解决了该潜在的错误。如果是,那么在出错报告310中将不报告任何出错消息,这进一步减少了假肯定出错消息的发生率。
另外,包含在API模拟器中的API模型可以包括依赖性规则。例如,可能在调用API之前,必须初始化将被传递至API的参数,或者必须调用API依赖的另一个API或某个其它函数。API模拟器360可以包括该依赖性规则,使得如果没有在调用API之前调用依赖函数,那么将由静态源代码分析器300生成错误。类似地,如果调用API之后必须调用另一函数或API,那么API模拟器360也可以包括该规则,使得如果没有按照所期望的方式调用该其它函数或API,那么生成错误。
如上所述,众多API是在二进制代码库中提供的,且用于实现API的源代码对将使用API的软件开发员不可用。本发明模型的实施例基于由API或SDK提供的文档来标识预期的API,以使静态源代码分析器300能够如下进一步描述的来实质上评估API调用。
可以理解,尽管静态源代码分析器300将输入处理器304描述为使得标准程序设计指令和API签名352被独立地处理,但是模拟器308和API模拟器360最好协作工作来评估是否恰当地调用API,以及API是否与源代码恰当地发挥作用。
示例性API的常规静态源代码分析器的处理为说明起见,呈现接收两个参数并返回成功/失败值的示例性API。在调用API之前,没有初始化由第二参数指向的存储器块。API在由第二参数指向的存储器块上执行某些操作。然而,如果第一参数没有满足某个条件,将不在由第二参数指向的存储器块上执行函数,实际上甚至不初始化该存储器。从而,如果无法初始化存储器块是一个问题问题,则用于评估API效果的常规静态源代码分析器将不能检测到该问题。
更具体地,示例性API使用以下API签名和源代码实现#define SOME_VALUE10bool SomeFunctionAPI(int a,int*b){if(a>0){*b=SOME_VALUE*a;
//没有向开发员揭示其它代码.
.
.
//没有向开发员揭示其它代码return true;
}
return false;
}无论由“其它代码”执行何种动作,仅当第一参数a大于零时才初始化b指向的存储器块,并对其作用。
进一步假设API是由用户期望提交用于静态源代码分析的源代码引用的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;
}静态源代码分析器不能访问SomeFunctionAPI的源代码实现。从而,常规的静态源代码分析器可以分析用于调用SomeFunctionAPI的句法,但是在不能访问源代码实现的情况下,将不评估API调用的语义。
在API调用之后的源代码行y=1/x中出现潜在的问题。不能访问API源代码实现的常规静态源代码分析器不能确定API可能返回x的什么值。在检查API的源代码实现中,如果z大于零,将初始化x,但是如果z值小于或等于零,那么将不初始化x。不能以其它方式由调用API的源代码初始化变量x。因此,如果没有初始化x,那么表达式y=1/x会导致对未初始化变量的除法。另一方面,如果z大于或等于零,初始化x并将其置为非零值,那么表达式y=1/x将产生定义的、可接受的结果。而且即使能够访问源代码实现,即使没有初始化z,也不可能预测API在值x上的结果。
某些常规模拟器可以进行关于x的假设。例如,假设静态源代码分析器可以假定初始化了x。另一方面,静态源代码分析器也可以被配置成假定如果x没有由调用API的源代码初始化,那么x将不被API初始化。类似地,假设静态源代码分析器可以假定由API返回的x的值是零或不等于零。无论何种情况,静态源代码分析器仅可以猜测x的值,因为常规静态源代码分析器不能确定将由API返回x的什么值。
结果是,因为常规静态源代码分析器不能确定x的值,y=1/x表达式存在问题。如下进一步描述的,取决于常规静态源代码分析器进行了何种假定,静态源代码分析器将不能检测错误、生成假的出错消息或纯粹偶然地产生适当的响应。
根据本发明的实施例建模的示例性API即使API开发员没有揭示API的源代码实现,根据本发明的实施例,静态源代码分析器仍适用于正确地标识源代码中潜在的错误。
图4示出了根据本发明,显示用于对API建模的逻辑步骤。在步骤402处开始API建模。在步骤404处,审阅关于API功能的API文档或其它信息。基于该对API信息的审阅,在步骤406处,为API标识恰当的句法。在步骤408处,标识API的依赖性规则。例如,依赖性规则可以指定是否必须初始化由传递给API的指针所指示的某个参数或存储器等,以及在API之后是否必须调用函数。在步骤410处,创建状态对象来对API的功能和/或依赖性建模。在步骤412处结束API建模。
静态源代码分析器一般使用状态对象来跟踪程序元素和变量的状态。因此,例如,在调用的API的前述例程中,如果调用了影响x的值的已知源代码实现的函数,那么可以使用状态对象来跟踪x的值以确定语句y=1/x中的除以x是否产生有效值。认识了源代码的已知句法和规则之后,可以使用状态机,例如,用于确定诸如无符号整数的原语是否以与作为无符号整数的原语一致的方式使用。
根据本发明的实施例,用户可以研究描述API的文档,以及使用API原语370(图3)来创建静态源代码分析器可以访问并评估AP的功能的模型。API原语370包括可以指定多个参数的签名,签名可以用于评估参数来确定它们是否满足某些条件,以确定是否恰当地调用API、API是否产生有效的结果以及类似的判断。
考虑示例性API,假定API文档提供以下信息句法bool SomeFunctionAPI(int A,int*p B)参数A,是[in(入)]参数,带符号整数,且必须被初始化为INT_MIN与INT_MAX之间的一个值。
pB,是[out(出)]参数,指向带符号整数的指针,且不能为NULL。
返回值如果该方法成功,则返回值为真;否则返回值为假。
功能基于参数A的值,初始化由参数pB指向的存储器块。
依赖性无限制-如果没有初始化参数A,那么该方法的行为是未定义的。
-如果参数A被初始化为>0的值,那么由参数pB指向的存储器块被初始化为非零的值,该方法调用成功并返回真。
-如果参数A被初始化为<=0的值,那么不访问由参数pB指向的存储器块,且如果之前没有初始化则它可能保持未初始化,该方法失败并返回假。
使用对API的功能的描述,以及关于使用API的限制,即使不能访问源代码实现,根据本发明的实施例,静态源代码分析器仍旧可以对API的操作进行建模和模拟。
如之前结合图3所述,在本发明的一个实施例中,在建模库中向静态源代码模拟器提供API原语使得静态源代码模拟器能够对API行为建模。API原语涉及处理存储器初始化、缓冲器、指针、存储器分配的功能和可以由API执行的其它功能。API原语可以用来指定当调用API时必须保持的某些条件,以及当对API的调用返回时被预期或保持为真的某些结果。
使用前述的API文档,可以使用含有指定的原语签名和函数的多个示例性API原语来建模API SomeFunctionAPI。例如,为四个API原语提供句法和功能描述,即使不能访问源代码实现,这些API原语也可用来基于从API或SDK文档已知的关于API的信息来对API功能建模,该描述如下CheckIntegerIsInitialized(int x)-验证x参数是否被初始化且在INT_MIN与INT_MAX的界限内的原语签名。如果整数参数x不满足指定的条件,那么模拟器生成未初始化变量警告。
CheckIntegerBoundsGreaterEqual(int x,int lower_bound,iht upper_bound)-验证整数参数x的值大于或等于整数参数lower_bound(下界)的值,但小于或等于整数参数upper_bound(上界)的值的原语签名。如果参数x不满足该指定条件,那么模拟器生成越界警告。
CheckPointerIsValid(int*p)-验证指向整数变量的指针的参数p指向有效存储器,从而验证该有效存储器对数据存储可用的原语签名。如果整数指针不指向有效的存储器,那么模拟器生成NULL指针解除引用警告。
ReturnIntegerValueGreaterThan(int*p,int lower_bound)-向模拟器指示指向整数变量的指针的参数p要被初始化为大于参数lower_bound的值的原语签名。从而,当模拟器解析在API调用之后涉及除以由指针p访问的整数变量的表达式时,模拟器将不会生成除以零或除以未定义值的警告。
可以理解,可以存在对应于可能由API或其它外部函数执行的任何数量的动作的任何数量的API原语。
使用某些API原语,基于从API文档获取的关于API的信息,可以对APISomeFunctionAPI建模以便于静态源代码分析器对源代码的更准确评估bool SomeFunctionAPI(int a,int*b){CheckIntegerIsInitialized(a);
CheckIntegerBoundsGreaterEqual(a,1,INT_MAX);
CheckPointerIsValid(b);
ReturnIntegerValueGreaterThan(&b,0);}因此,当模拟器标识对SomeFunctionAPI的调用时,模拟器API搜索由静态源代码模拟器检查的模型的储存库。在为SomeFunctionAPI找到模型之后,访问模型以协助评估源代码的行为,包括由模型储存库中的模型表示的API的行为。从而,如下进一步描述,静态源代码分析器能够减少可能由不能访问由源代码调用的API的源代码实现的静态源代码分析器生成的噪声和假肯定出错消息。
表示API的潜在模型的状态对象的图形描述图5是创建来对示例性API建模的状态对象500的图形描述。应该注意,状态对象仅使用API文档中提供的信息,而扩充静态源代码分析器以在源代码上下文内有意义地评估API调用的参数。
状态对象500包括评估API调用的句法的状态502。因为通过声明API使用“extern”句法来将其指定为外部函数,所以常规的静态源代码分析器将识别该“extern”句法调用源代码不可用的模块,并将忽略表达式的其余句法。从而,状态502扩充了静态源代码分析器,使得其能够确定是否使用了API所定义的句法。状态502可以包括顺序测试以确定是否提供一连串所需参数的多个状态。如果否,在状态504处生成句法错误,它将被包含在由静态源代码分析器产生的出错报告中。另一方面,如果句法正确,或一旦在状态504处生成句法错误,那么状态对象500前进至状态506。
在状态506处,确定是否满足API的依赖性条件。如果否,那么在状态508处,生成包含在由静态源代码分析器产生的出错报告中的依赖性错误。例如,如在API文档中指定如果仅在调用另一API之后或必须执行某些其它函数之后调用API,那么可能存在依赖性错误。可以包含多个依赖性检查状态506,其中每一个都评估一特定的依赖性。如果满足依赖性或在状态508处生成依赖性错误,那么状态对象500前进至状态510。
在状态510处,确定第一变量是否大于零。如果否,那么在状态512处,不将第二变量标记为已被初始化或已被处理。另一方面,如果在状态510处确定第一变量大于零,那么在状态514处,第二变量被标记为已被初始化或已被处理。
状态对象500协同由静态源代码分析器使用的其它状态对象一起操作。因此,例如,当定义了x时,由静态源代码分析器为其创建状态对象。因为x还没有被初始化,其状态对象指示它还没有被初始化。在没有对API功能的某些理解的情况下,静态源代码分析器可能假定API或者从未初始化[out]变量,从而导致假肯定,或者总是初始化[out]变量,从而忽略潜在的问题。因此,本发明中对API的建模确保向用户提供更好且更准确的信息。
调用示例性API的代码的静态源代码分析一方面,不是如图6A所示的对API进行建模的静态源代码分析器600可以假定,除非如所示x是由源代码610初始化的(源代码610不包括API源代码),否则x没有被初始化。因此,不考虑API调用620可能初始化x(当z大于零)的概率,第11行的表达式y=1/x将导致出错消息640a,因为如果没有初始化x,它将导致除以未定义的值。图6A的出错消息640a最终结果是准确的语句,因为在表达式650a中将变量z置为零且因为z不大于零将不初始化x,从而API没有初始化x。然而,出错消息640为准确的纯粹是偶然的,因为常规静态源代码分析器不适用于评估API的功能,因此不能确定API是否初始化了x。
然而,如图6B所示,在没有API模型的好处的情况下,静态源代码分析器600a即使在x初始化时也将生成类似同样的出错消息。图6B中,静态源代码分析器600分析除语句650a(图6A)的改变以外与源代码610完全相同的源代码610′,在650a中初始化z并将其置为等于零,而在API调用620之前的语句650b中,初始化z并将置为等于一。从而,如上所述,因为z被初始化且大于零,API将执行x上的函数并将x返回为某个非零数字。从而,表达式630不导致除以未初始化的变量。尽管如此,仍旧生成指示除以未初始化变量的问题的出错消息640b,因为源代码分析器600不能确定语句650b使得API调用620返回有效且不为零的值x。出错消息640b构成明显不正确的假肯定,因为表达式630不导致除以未定义、未初始化的值。
图6A或图6B的结果都是不可接受的。出错消息640a呈现了可能不为真的语句,而软件开发员可能难以试图调试代码来标识及可能更正引起静态源代码分析器600a生成该消息的问题。由静态源代码分析器生成的出错消息640b也是不可接受的,因为它在不存在错误的地方指示了错误;软件开发员不太可能修改代码以便阻止该消息;从而,软件开发员必须忽略出错消息640b。
或者,如图7A中所示,静态源代码分析器700被配置成在假定在源代码610′中初始化了传递给诸如API调用620中调用的外部函数等外部函数的参数的情况下操作。作出该假设,静态源代码分析器700不将第11行的表达式630,y=1/x视为可能会引起错误。因此,静态源代码分析器700生成指示没有检测到错误的消息740a。偶然地,消息740a是正确的,因为表达式650b初始化了z并将其置为等于一,导致API初始化并返回x的非零值。
然而,在没有将静态源代码分析器700配置成分析API的情况下,该假设可能是错误的。如图7B中所示,静态源代码分析器700分析源代码610,其中在语句650a中初始化变量z,并将其置为零,所作假设是错误的。因为z被初始化为零,那么在源代码600中,API调用620不初始化x。因此,表达式导致除以未定义的值。然而,消息740b指示没有发现错误。因此,静态源代码分析器没有被配置成对API建模,再一次生成不准确的消息740b。再次,静态源代码分析器700生成可能是假肯定或可能无法包括实际错误的消息。
相反,使用其中静态源代码分析器对API建模的本发明的实施例,可以避免上述问题。如图8A中所示,静态源代码分析器800分析其中由语句650a初始化变量z并将其置为等于零的源代码610。作为结果,API调用620导致没有初始化变量x,导致表达式630中除以未定义的值。因为静态源代码分析器800包括使用API原语的API模型,静态源代码分析器正确地对API的功能建模,静态源代码分析器识别非法函数并生成准确的出错消息840a。
而且,如图8B中所示,当静态源代码分析器800分析包括在API调用620之前将z初始化为1的表达式650b的源代码610′时,API将返回x的非零值,且表达式630也不表示非法操作。因为静态源代码分析器800使用如前所述的API原语对API的功能建模,静态源代码分析器正确地确定表达式650中对z的初始化初始化了x并返回非零值,所以它返回指示没有发现错误的消息840b。因此,在源代码610和610′的情况下,静态源代码分析器800均生成准确的报告,它标识真正的错误,但不包括假肯定。
使用API模型的静态源代码分析的处理图9是示出根据本发明的实施例,用于分析源代码的逻辑步骤的流程图900。在步骤902处开始分析。在步骤904处,接收源代码。在步骤906处,标记或忽略注释及其它非程序设计指令的内容。在步骤908处,模拟源代码元素。在判断步骤910处,确定源代码元素是否标识非标准元素,诸如API调用或其它外部函数调用。如果元素被标识为非标准元素,那么在判断步骤912处,确定该非标准元素是否表示API调用。如果否,那么在步骤914处,生成消息“未识别的表达式”。另一方面,如果在判断步骤912处确定该非标准元素是API调用,那么在步骤916处,确定是否存在对该API的分析模型。如果否,那么在步骤918处,生成指示对该API没有模型可用的出错消息。
另一方面,如果在判断步骤916处确定API模型可用,或者之前在判断步骤910处确定源代码元素为标准源代码元素,那么在步骤920处,确定在源代码元素中是否检测到错误。如果是,那么在步骤922处生成适当的出错消息。另一方面,如果在判断步骤920处没有检测到错误,或者一旦在914、908或922处生成适当的消息,流程图900前进至判断步骤924处。在判断步骤924处,确定是否模拟了所有源代码元素。如果否,那么在步骤926处,标识要被评估的下一源代码元素,且在步骤908处评估下一源代码元素。或者,一旦在步骤924处确定已经模拟了所有源代码元素,那么生成包含在之前步骤中生成的所有出错消息的报告。在步骤930处结束静态源代码分析。
尽管结合实现本发明的较佳形式及其修改来描述了本发明,但是本领域的普通技术人员可以理解,可以对本发明进行所附权利要求书范围内的众多其它修改。从而,本发明的范围不旨在由以上描述以任何方式限制,而是完全参考所附权利要求书来确定。
权利要求
1.一种用于分析其函数源代码实现不可用的外部函数的调用的方法,包括以下步骤(a)标识由源代码对所述外部函数的不恰当调用导致的至少一个潜在错误;(b)标识将导致所述潜在错误的至少一个条件;(c)创建函数的模型以测试导致潜在错误并当发现所述条件时将触发生成出错消息的所述至少一个条件;以及(d)将所述模型与源代码分析器相关联,使得当所述源代码由所述源代码分析器分析时,所述模型被应用来评估对所述外部函数的调用。
2.如权利要求1所述的方法,其特征在于,所述外部函数包括应用程序编程接口。
3.如权利要求1所述的方法,其特征在于,还包括基于实现所述外部函数的要求,标识将导致所述潜在错误的至少一个条件的步骤。
4.如权利要求1所述的方法,其特征在于,所述至少一个条件包括以下的至少其中之一(a)所述应用程序编程接口可接受的输入参数的不正确输入类型;(b)所述应用程序编程接口可接受的输入参数的不正确输入内容范围;(c)可由所述应用程序编程接口生成的输出参数的不正确输出类型;(d)可由所述应用程序编程接口生成的输出参数的不正确输出内容范围;(e)不能调用在调用所述外部函数之前必须被调用的先决函数;以及(f)不能调用在调用所述外部函数之后必须被调用的后决函数。
5.如权利要求1所述的方法,其特征在于,所述模型是使用可用于测试导致潜在错误的所述至少一个条件的多个原语来创建的。
6.如权利要求5所述的方法,其特征在于,所述源代码分析器包括被配置成存储所述创建的模型的模型储存库,使得所述源代码分析器能够在评估源代码及标识对所述外部函数的引用之后访问所述模型。
7.一种含有用于执行如权利要求1所述的步骤的机器可执行指令的存储器介质。
8.一种用于使源代码分析器适用于评估其函数源代码实现不可用的外部函数的方法,包括以下步骤(a)使所述源代码分析器适用于识别及分析所述外部函数;(b)标识由源代码对所述外部函数的不恰当调用导致的至少一个潜在错误;(c)标识将导致所述潜在错误的至少一个条件;(d)创建所述函数的模型以测试导致潜在错误并当发现所述条件时将触发生成出错消息的所述至少一个条件;(e)将所述模型包含在源代码分析器内,使得当所述源代码由所述源代码分析器分析时,所述模型被应用来评估对所述外部函数的调用;以及(f)在当分析所述源代码时由所述源代码分析器生成的出错报告中包含由所述模型触发的出错消息。
9.如权利要求8所述的方法,其特征在于,所述外部函数包括应用程序编程接口。
10.如权利要求8所述的方法,其特征在于,还包括基于实现所述外部函数的要求,标识将导致潜在错误的所述至少一个条件的步骤。
11.如权利要求8所述的方法,其特征在于,所述至少一个条件包括以下的至少其中之一(a)所述应用程序编程接口可接受的输入参数的不正确输入类型;(b)所述应用程序编程接口可接受的输入参数的不正确输入内容范围;(c)可由所述应用程序编程接口生成的输出参数的不正确输出类型;(d)可由所述应用程序编程接口生成的输出参数的不正确输出内容范围;(e)不能调用在调用所述外部函数之前必须被调用的先决函数;以及(f)不能调用在调用所述外部函数之后必须被调用的后决函数。
12.如权利要求8所述的方法,其特征在于,所述模型是使用可用于测试导致潜在错误的所述至少一个条件的多个原语来创建的。
13.如权利要求12所述的方法,其特征在于,所述源代码分析器包括被配置成存储所创建的模型的模型储存库,使得所述源代码分析器能够在评估源代码及标识对所述外部函数的引用之后访问所述模型。
14.如权利要求8所述的方法,其特征在于,还包括使所述源代码分析器适用于评估为选取的计算环境所提供的软件开发工具包中所包含的二进制库中含有的多个外部函数的步骤。
15.一种含有用于执行如权利要求8所述的步骤的机器可执行指令的存储器介质。
16.一种用于分析对其函数源代码实现不可用的外部函数的调用的系统,所述系统包括(a)至少一个用户输入设备;(b)显示器;(c)与所述输入设备和显示器通信的处理器;以及(d)与所述处理器通信的存储器,所述存储器存储使得所述处理器实现多个功能的数据和机器指令,所述功能包括(i)标识由源代码对所述外部函数的不恰当调用导致的至少一个潜在错误;(ii)标识将导致所述潜在错误的至少一个条件;(iii)创建函数的模型以测试导致潜在错误并当发现所述条件时将触发生成出错消息的所述至少一个条件;以及(iv)将所述模型与源代码分析器相关联,使得当所述源代码由所述源代码分析器分析时,所述模型被应用来评估对所述外部函数的调用。
17.如权利要求16所述的系统,其特征在于,所述外部函数包括应用程序编程接口。
18.如权利要求16所述的系统,其特征在于,所述机器指令还引起所述处理器基于实现所述外部函数的要求,标识将导致潜在错误的所述至少一个条件。
19.如权利要求16所述的系统,其特征在于,所述至少一个条件包括以下的至少其中之一(a)所述应用程序编程接口可接受的输入参数的不正确输入类型;(b)所述应用程序编程接口可接受的输入参数的不正确输入内容范围;(c)可由所述应用程序编程接口生成的输出参数的不正确输出类型;(d)可由所述应用程序编程接口生成的输出参数的不正确输出内容范围;(e)不能调用在调用所述外部函数之前必须被调用的先决函数;以及(f)不能调用在调用所述外部函数之后必须被调用的后决函数。
20.如权利要求16所述的系统,其特征在于,所述模型是使用可用于测试导致潜在错误的所述至少一个条件的多个原语来创建的。
全文摘要
在处理诸如应用程序编程接口(API)等源代码不可用的外部函数中,使用模型来评估是否恰当地调用了该外部函数。标识由对外部函数的不恰当调用潜在导致的错误以及将导致该潜在错误的至少一个条件。创建模型来测试将该导致潜在错误的条件。当发现条件时,触发生成出错消息。模型与源代码分析器相关联,使得当由源代码分析器分析源代码时,模型被应用来评估对外部函数的调用。可以从描述外部函数或API的操作的文档中获取潜在的错误及导致错误的条件,诸如输入/输出参数错误或依赖性错误。
文档编号G06F9/44GK1825278SQ20061000597
公开日2006年8月30日 申请日期2006年1月20日 优先权日2005年2月22日
发明者M·E·朱伯兰 申请人:微软公司
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1