程序测试方法、装置、电子设备及存储介质
技术领域
本公开涉及测试技术领域,具体而言,本公开涉及一种程序测试方法、装置、电子设备及存储介质。
背景技术
针对程序项目,进行测试活动能够提高程序项目的质量与可靠性,以软件程序项目为例,软件测试阶段的测试活动包括:单元测试、集成测试、***测试、回归测试、性能测试、验收测试等阶段的测试活动。
现有技术中,往往采用模糊测试技术进行软件测试,即:将自动或半自动生成的随机数据输入到测试程序中,监测并收集程序异常表现以发现可能的程序错误,但该项技术往往依赖于人工编写测试的驱动函数,或人工编写的测试输入样例,导致该项技术无法进行大规模的应用。
发明内容
本公开的目的旨在至少能解决上述的技术缺陷之一,特提出以下技术方案:
第一方面,提供了一种程序测试方法,包括:
对待测试程序的程序代码进行静态分析,获取所述程序代码中的待测函数,解析所述待测函数获得所述待测函数的关键信息;
基于所述待测函数的关键信息生成用于驱动待测试程序进行测试的测试驱动代码;
利用所述测试驱动代码对所述程序代码进行模糊测试,以确定待测试程序中的异常信息,所述异常信息包括:错误代码和安全漏洞中的至少一个。
第二方面,提供了一种程序测试装置,包括:
获得关键信息模块,用于对待测试程序的程序代码进行静态分析,获取所述程序代码中的待测函数,解析所述待测函数获得所述待测函数的关键信息;
生成测试驱动代码模块,用于基于所述待测函数的关键信息生成用于驱动待测试程序进行测试的测试驱动代码;
模糊测试模块,用于利用所述测试驱动代码对所述程序代码进行模糊测试,以确定待测试程序中的异常信息,所述异常信息包括:错误代码和安全漏洞中的至少一个。
第三方面,提供了一种电子设备,包括存储器、处理器及存储在存储器上并可在处理器上运行的计算机程序,处理器执行程序时实现本公开第一方面所示的程序测试方法。
第四方面,提供了一种计算机可读存储介质,计算机可读存储介质上存储有计算机程序,该程序被处理器执行时实现本公开第一方面所示的程序测试方法。
本公开提供的技术方案带来的有益效果是:
本公开提供的程序测试方法,首先通过静态分析技术实现待测函数信息的自动获取,再基于待测函数的关键信息自动生成测试驱动代码,基于测试驱动代码对所述程序代码进行模糊测试,实现对错误代码、安全漏洞等异常信息的检测,在该测试过程中,无需依赖人工编写测试的驱动函数,或人工编写测试输入样例,大大提高了测试过程的自动化程度,实现全流程自动化的程序自动化模糊测试,有利于实现模糊测试技术的大规模、自动化应用。
本公开提供的程序测试方法,通过***用于统计覆盖率信息的代码、用于安全属性检查的代码,能够有导向性地选择和生成新的测试输入,更快地触发不经常执行的代码,有利于更加全面、准确地检测出程序代码中的代码错误。
本公开附加的方面和优点将在下面的描述中部分给出,这些将从下面的描述中变得明显,或通过本公开的实践了解到。
附图说明
本公开上述的和/或附加的方面和优点从下面结合附图对实施例的描述中将变得明显和容易理解,其中:
图1为本公开一个实施例提供的程序测试方法的流程图;
图2为本公开另一个实施例提供的包含***辅助代码的程序测试方法的流程图;
图3为本公开一个实施例提供的对待测试程序的程序代码进行静态分析,获取所述程序代码中的待测函数,解析所述待测函数获得所述待测函数的关键信息的流程图;
图4为本公开一个实施例提供的生成测试驱动代码之前,进行参数转换的流程图;
图5为本公开实施例提供的一种程序测试装置的结构示意图;
图6为本公开实施例提供的一种电子设备的结构示意图。
具体实施方式
下面详细描述本公开的实施例,实施例的示例在附图中示出,其中自始至终相同或类似的标号表示相同或类似的元件或具有相同或类似功能的元件。下面通过参考附图描述的实施例是示例性的,仅用于解释本公开,而不能解释为对本公开的限制。
本技术领域技术人员可以理解,除非特意声明,这里使用的单数形式“一”、“一个”、“所述”和“该”也可包括复数形式。应该进一步理解的是,本公开的说明书中使用的措辞“包括”是指存在特征、整数、步骤、操作、元件和/或组件,但是并不排除存在或添加一个或多个其他特征、整数、步骤、操作、元件、组件和/或它们的组。应该理解,当我们称元件被“连接”或“耦接”到另一元件时,它可以直接连接或耦接到其他元件,或者也可以存在中间元件。此外,这里使用的“连接”或“耦接”可以包括无线连接或无线耦接。这里使用的措辞“和/或”包括一个或更多个相关联的列出项的全部或任一单元和全部组合。
本领域技术人员可以理解,除非另外定义,这里使用的所有术语(包括技术术语和科学术语),具有与本发明所属领域中的普通技术人员的一般理解相同的意义。还应该理解的是,诸如通用字典中定义的那些术语,应该被理解为具有与现有技术的上下文中的意义一致的意义,并且除非像这里一样被特定定义,否则不会用理想化或过于正式的含义来解释。
模糊测试:一种程序测试技术,将大量的测试数据输入到目标程序中进行测试,获得各程序代码的执行信息,收集程序异常表现以发现可能的程序错误。
静态分析:一种代码分析技术,是在不运行代码的方式下,通过词法分析、语法分析、控制流分析等技术对程序代码进行扫描,验证代码是否满足规范性、安全性、可靠性、可维护性等指标,被用于程序测试和正确性验证。
污点分析,是一种数据流分析方法,其跟踪程序的处理过程,可以记录数据流的流向,从而找到目的数据和源数据的依赖关系,将可疑的不可信源数据标记为被污点数据,然后根据某些规则进行传播,达到检测软件漏洞的目的。为使本公开的目的、技术方案和优点更加清楚,下面将结合附图对本公开实施方式作进一步地详细描述。
本公开提供的程序测试方法、程序测试装置、电子设备及存储介质,旨在解决现有技术的如上技术问题,本公开提供的程序测试方法可以适用于可以运行和测试的程序项目,包括但不限于软件程序项目,由于,硬件程序项目的测试流程中,也存在采用软件测试的部分,因此,硬件程序项目也可以采用本公开提供的方案进行程序测试。
下面以具体地实施例对本公开的技术方案以及本公开的技术方案如何解决上述技术问题进行详细说明。下面这几个具体的实施例可以相互结合,对于相同或相似的概念或过程可能在某些实施例中不再赘述。下面将结合附图,对本公开的实施例进行描述。
本公开实施例中提供了一种可能的实现方式,如图1所示,提供了一种程序测试方法,该方案可在服务器端执行,包括以下步骤:
S110,对待测试程序的程序代码进行静态分析,获取所述程序代码中的待测函数,解析所述待测函数获得所述待测函数的关键信息;
S120,基于所述待测函数的关键信息生成用于驱动待测试程序进行测试的测试驱动代码;
S130,利用所述测试驱动代码对所述程序代码进行模糊测试,以确定待测试程序中的异常信息,所述异常信息包括:错误代码和安全漏洞中的至少一个。
待测试程序由程序代码表征,获取表征待测试程序项目的程序代码,对待测试程序的程序代码进行静态分析,即,对程序代码进行扫描以获取程序代码中的待测函数以及程序代码的结构信息、变量信息和数据信息等,其中,待测函数可以是与程序安全、运行环境等相关的函数。解析待测函数,获得待测函数的关键信息,如:参数列表、参数类型、参数内部构成等关键信息。
结合词法分析和语法分析,静态分析可以检查所测试程序违反编程标准的错误,如通过统计、对比如下数据:模块大小、模块结构、注释的约定和各种类型源语句的出现次数等,发现待测试的程序代码中的错误代码。还能完成对一些特性的统计,如函数过程引用情况、标识符使用的交叉索引、标识符在每个语句中使用的情况、任何输入输出语句都执行不到的语句代码段、全局变量和局部变量的各种统计等,根据统计结果确定程序代码中的错误代码。
对待测函数的参数列表、参数类型、参数内部构成等关键信息进行分析、处理,以生成用于驱动测试程序的测试驱动代码,本公开提供的方案,利用待测函数的关键信息生成测试驱动代码,测试驱动代码用于驱动测试程序对待测函数的测试。
利用测试驱动代码对待测试程序的程序代码进行模糊测试,模糊测试通过向待测试***提供非预期的输入并监视异常结果来发现安全漏洞,即:用随机数据测试待测程序,监测遭到破坏的位置,该位置即为安全漏洞的位置。本公开通过测试驱动代码驱动测试进行,根据测试结果确定待测试程序中的错误代码、安全漏洞等异常信息。
进一步地,为了增加模糊测试中对随机输入的控制,让模糊测试能更加高效地挖掘安全漏洞,可以根据已经执行过的随机输入产生的反馈信息调整测试程序的输入。或者,还可以根据程序运行中的代码覆盖情况,基于执行过的随机输入已经覆盖的执行路径信息,有导向性地选择和生成新的测试输入,通过特定算法将程序的执行路径导向未执行过的路径,更快地触及不经常执行的代码,以挖掘程序代码中的代码错误及安全漏洞。
本公开提供的程序测试方法,首先通过静态分析技术实现待测函数信息的自动获取,再基于待测函数的关键信息自动生成测试驱动代码,基于测试驱动代码对所述程序代码进行模糊测试,实现对异常信息,如:错误代码及安全漏洞的检测,在该测试过程中,无需依赖人工编写测试的驱动函数,或人工编写测试输入样例,大大提高了测试过程的自动化程度,实现全流程自动化的程序自动化模糊测试,有利于实现模糊测试技术的大规模、自动化应用。
为了更清楚本公开提供的程序测试方案及其技术效果,接下来以多个实施例对其具体实施方案进行详细阐述。本公开实施例中提供了一种程序测试方法的实现方式,S110的对待测试程序的程序代码进行静态分析之后,还包括:***辅助代码,所述辅助代码包括覆盖率统计代码、安全属性检查代码中的至少一个,其中,***覆盖率统计代码的步骤,包括:
A1,将所述程序代码划分为多个基本块,所述基本块是程序代码中顺序执行且仅有一个出入口的语句序列;
A2,在每个所述基本块中***用于统计覆盖率信息的代码。
程序代码的基本块,是代码序列中一组顺序执行的语句序列,只有一个入口和一个出口,而划分基本块的实质就是定义入口和出口语句。
具体地,利用静态分析技术对待测试程序的程序代码进行扫描、词法分析、语法分析等操作,获得待测函数的抽象语法树,通过对待测函数进行抽象语法树分析将程序代码划分为多个基本块,在每个基本块中***用于统计覆盖率信息的覆盖率统计代码,由于每个基本块仅有一个出口及入口,较容易获得代码测试的覆盖率信息。
而且,覆盖率统计代码的***能够通过程序控制,无需人工参与,实现辅助代码***的自动化。
在程序代码的每个基本块中***用于统计覆盖率信息的代码,根据代码执行结果获取程序运行过程中的代码覆盖情况,在后续基于统计覆盖率信息的代码进行模糊测试时,基于代码覆盖情况,有导向性地选择和生成新的测试输入,以更快地触发不经常执行的代码,有利于更加全面地检测出程序代码中的代码错误。
其中,***安全属性检查代码的步骤,包括:
B1,获得程序代码的安全关键位置;
B2,在所述安全关键位置处***用于安全属性检查的代码。
发明人在研发过程中发现,单纯依靠模糊测试,无法发现一些代码错误类型,例如环绕错误、精度丢失、整数溢出等,本公开通过在程序代码中***进行代码错误检查的程序属性,该程序属性可以以断言语句的形式呈现,可以有效地检测出这些代码错误。
具体地,利用静态分析技术对待测试程序的程序代码进行扫描、词法分析、语法分析等操作,获得待测函数的抽象语法树,通过对抽象语法树进行抽象语法树分析获得程序代码的安全敏感位置信息,在安全敏感位置处***用于安全属性检查的代码。
安全属性检查能够检查程序代码中的代码错误,在程序代码的安全关键位置***用于安全属性检查的代码,安全关键位置为安全敏感区,如:安全关键位置关系到整个程序代码的安全,或者,安全关键位置频繁出现安全问题。将安全属性检查的代码置于代码安全关键位置处,以便后续基于安全属性检查的代码进行模糊测试时,能够更加准确、及时地发现安全关键位置处的安全漏洞,有利于提高代码错误类型的检测全面性,使得检测出的代码错误类型覆盖面更广。
而且,将安全关键位置处***安全属性检查的代码,还能够检测出一些特定类型的代码错误,例如:浮点数精度丢失、整数溢出等,由于这些代码错误并不会触发程序崩溃,一般的程序测试无法发现这些特定类型的代码错误,本公开通过在程序中***安全属性检查的代码,使得程序测试技术能够检测出这些代码错误类型,拓展了程序错误检测的能力和边界,实现对传统测试技术能力的增强。
进一步地,向包含上述两种辅助代码的程序测试方法的流程图请参考图2,如下子步骤:
S141,获得所述程序代码的基本块及安全关键位置;
S142,在所述基本块中***用于统计覆盖率信息的代码,并在所述代码安全关键位置处***用于安全属性检查的代码;
在此基础上,利用所述测试驱动代码对所述程序代码进行模糊测试,包括:
利用所述统计覆盖率信息的代码、所述安全属性检查的代码及所述测试驱动代码对所述程序代码进行模糊测试。
通过利用静态分析技术对程序代码进行静态分析,获得程序代码的基本块及安全关键位置,在所述基本块及安全关键位置***辅助代码,辅助代码包括:用于统计覆盖率信息的代码及用于安全属性检查的代码。具体地,对程序代码中的每个基本块***用于统计覆盖率信息的代码,以及对代码安全关键位置***安全属性检查的代码,不同辅助代码的***无顺序限制。辅助代码的***能够通过程序控制,无需人工参与,实现辅助代码***的自动化。
在基本块中***用于统计覆盖率信息的代码,并在代码安全关键位置处***用于安全属性检测的代码,然后,利用用于统计覆盖率信息的代码、安全属性检查的代码以及测试驱动代码对程序代码进行模糊测试。
由于基于统计覆盖率信息的代码进行模糊测试,即利用统计覆盖率信息的代码和测试驱动代码对程序代码进行模糊测试,能够实现有导向性地选择和生成新的测试输入,更快地触发不经常执行的代码,更加全面地检测出程序代码中的代码错误。利用安全属性检查的代码及测试驱动代码对程序代码进行模糊测试,能够准确、及时地发现安全关键位置处的安全漏洞,拓展程序错误检测的能力和边界,提高代码错误类型的检测全面性,因此,结合统计覆盖率信息的代码、所述安全属性检查的代码及所述测试驱动代码对所述程序代码进行模糊测试能够提高程序测试的准确性、全面性及效率。
需要说明的是,***辅助代码的步骤(S141-S142)可以在获取待测试程序的步骤之后,即可以在S120之后,也可以S120之前甚至是与S120同步执行,无严格时间顺序上的限制。
进一步地,对***统计覆盖率信息的代码及安全属性检查的代码后的程序代码进行静态分析、调整,使得***代码后的程序代码满足语法、语义的规范性及正确性。
可选地,B2的在安全关键位置处***用于安全属性检查的代码,可以通过如下方式实现,包括:
B21,获取预先集成的多种针对不同代码安全问题的安全属性规则;
B22,获取程序代码的抽象语法树,并对所述抽象语法树进行污点分析,获得抽象语法树上各代码安全关键位置处的代码安全问题;
B23,在代码安全关键位置处***与该位置处的代码安全问题相匹配的安全属性规则的代码。
其中,预先获取并集成多种不同代码安全问题及其对应的安全属性规则,通过对抽象语法树进行静态分析和污点分析,匹配安全属性规则。
具体地,利用静态分析技术,通过词法分析、语法分析、控制流分析等技术对程序代码进行扫描,将程序代码的词法单元流转换成由元素逐级嵌套所组成的代表程序语法结构的树,即获得抽象语法树。
抽象语法树能够实现进行代码语法的检查、代码错误提示等功能,因此,通过对抽象语法树进行污点分析,获得各代码安全关键位置处的代码安全问题。
利用污点分析技术跟踪程序代码执行过程中的数据流向,根据对数据流的分析获得抽象语法树上各代码安全关键位置处的代码安全问题,根据每个代码安全位置处的代码安全问题获得与之匹配的安全属性规则。
由于静态分析技术,无需运行程序代码,可以只是通过对代码的静态扫描对程序进行分析,因此在进行程序代码执行之前,即可获取程序代码的抽象语法树,与动态分析相比,基于静态分析对程序代码的检测速度更快、效率更高。
本公开实施例提供的方案,结合静态分析与污点分析技术,无需执行程序代码也能确定代码安全关键位置的代码安全问题,进而确定与该代码安全问题相匹配的安全属性规则。
在一种可行的实施方式中,S110提供的对待测试程序的程序代码进行静态分析,获取程序代码中的待测函数,解析该待测函数获得待测函数的关键信息的步骤,可以通过如下方式实现,其流程图如图3所示,包括:
S330,基于程序测试的场景信息确定函数的筛选条件,利用所述筛选条件从所述程序代码对应的函数中筛选出待测函数;
S340,解析所述待测函数获得其中的关键信息,所述关键信息包括参数列表、参数类型、参数内部构成中的至少一个。
一种可选方式中,在确定函数的筛选条件之前,还需要获得程序代码对应的程序,可以通过如下方式进行,包括:
S310,对所述程序代码进行代码加载、拆解,获得程序代码的结构化信息,其中,结构化信息包括:程序组成、作用域、变量类型、抽象语法树中的至少一种;
S320,对所述结构化信息进行语法分析、词法分析中的至少一种处理,获取所述程序代码中的所有函数。
对程序代码进行代码读取、加载,获得程序项目的源代码,将该源代码拆解后通过文本格式展示,基于文本格式的源代码获取程序组成、作用域、变量类型、抽象语法树等一系列结构化信息,以抽象语法树为例,抽象语法树标识出了编程语言的源代码的结构,抽象语法树上包括元素逐级嵌套的语法结构,这种语法结构及其在语法树上的位置关系形成结构化信息。
对程序代码的结构化信息进行语法分析和/或词法分析等处理,获取程序代码中的所有函数。
获取程序测试的场景信息,基于程序测试的场景信息确定用于筛选程序代码中待测函数的筛选条件,并利用筛选条件筛选所有函数获得待测函数。基于程序测试的场景信息形成的筛选条件对程序代码中的所有函数进行筛选,预先根据场景信息确定的筛选条件,如:仅对开放调用接口进行检查,或是仅对远程调用接口进行检查等。
根据确定的筛选条件筛选所有函数得到待测函数,解析所述待测函数获得待测函数的参数列表、参数类型、参数内部构成等关键信息,以便后续基于关键信息确定测试驱动代码。
本实施例提供了一种获得待测函数的关键信息的方式,在获得待测函数的关键信息的过程中,通过筛选条件对待测函数进行筛选,使得最终筛选出来的待测函数与程序测试的场景信息相符,减少待测函数的数量,有利于提高程序测试的效率。
在一种可选实施例中,基于待测函数的关键信息生成测试驱动代码的步骤,包括:
C1,根据所述关键信息中的参数类型将待测函数划分为基本待测函数和复杂待测函数;
C2,依据预设的测试驱动规则对所述复杂待测函数进行规则匹配,并根据与所述复杂待测函数相匹配的测试驱动规则对应的处理逻辑来处理所述复杂待测函数的关键信息,生成测试驱动代码。
本方案主要针对参数为复杂变量类型的待测函数,进行测试驱动规则匹配,按照匹配的测试驱动规则的处理逻辑生成测试驱动代码,过程如下:
对待测函数的参数信息进行数据分析,根据参数类型将待测函数划分为基本变量类型对应的基本待测函数,以及复杂变量类型对应的复杂待测函数,其中,复杂变量类型为除去基本变量类型之外的变量类型。
测试驱动规则存在多种,每种测试驱动规则的处理逻辑可能存在差异,针对复杂待测函数,首先进行测试驱动规则的匹配,根据待测函数的参数内部结构获得与复杂待测函数相匹配的测试驱动规则,再根据测试驱动规则的处理逻辑处理复杂待测函数的关键信息生成测试驱动代码,生成的测试驱动代码能够实现对待测函数的驱动。
针对基本变量类型的待测函数,获得测试驱动代码的过程如下:
对待测函数的参数列表、参数类型、参数内部结构等关键信息进行分析、处理,生成语法和语义正确的测试驱动代码。
本方案预先将待测函数划分为基本待测函数和复杂待测函数,针对复杂待测函数,进行测试驱动规则的匹配,根据匹配的测试驱动规则的处理逻辑处理复杂待测函数的关键信息,以生成测试驱动代码,按照测试驱动规则的处理逻辑处理关键信息有利于,针对复杂待测函数生成针对性的测试驱动代码,有利于提升测试效率及测试效果。
可选地,将生成的测试驱动代码进行语法检查,将通过语法检查后的测试驱动代码写入文件,使得测试驱动代码语法、语义符合代码的规范性、安全性等指标。
在此基础上,本公开还提供了一种可行的实施例,在生成测试驱动代码之前,还能通过如下方式进行参数转换,其流程图如图4所示,包括:
S410,获取用于进行程序测试的测试参数,对所述测试参数进行参数信息分析,获得各测试参数的数据类型;
S420,根据所述数据类型将所述测试参数划分为基本变量类型对应的测试参数及复杂变量类型对应的测试参数;其中,基本变量类型对应的测试参数能够在模糊测试中通过字节码读取的方式进行参数赋值;
S430,确定测试驱动代码中将复杂变量类型转换为基本变量类型的转换代码,以利用所述转换代码将所述复杂变量类型对应的测试参数解析为由至少一种基本变量类型构成的参数。
在此基础上,利用测试驱动代码对程序代码进行模糊测试,包括:
利用所述转换代码,将复杂变量类型对应的测试参数转换为基本变量类型的测试参数,以在模糊测试过程中,同样通过字节码读取的方式进行测试参数的赋值。
具体地,测试参数是用于模糊测试的测试输入数据,对获取到的测试参数进行参数信息分析,获取测试参数的数据类型,由于测试参数的可以是随机选取的,因此,测试参数的数据类型可以有多种,如:定长的变量类型,如:整型、布尔型,还有非定长的数据类型,如:字符串、切片、字典等数据类型,嵌套数据类型,如:结构体、指针等。
但是模糊测试过程中,许多程序语言原生的底层设计中,只有定长的变量类型,根据参数的数据结构将参数划分为基本变量及复杂变量。
一种实施例中,预先设定基本变量类型,如:具有预设固定长度的数据类型,才能通过字节码读取的方式进行赋值,其他非定长的数据类型无法通过这种方式进行参数赋值,可能导致进行模糊测试的数据片面化,导致测试效果不佳。
针对该种情况,本公开实施例提供一种可选方式进行测试参数的格式转换,包括:利用测试参数的参数类型将测试参数划分为基本变量类型对应的测试参数以及复杂变量类型对应的测试参数,基本变量类型对应的测试参数能够在模糊测试中通过字节码读取的方式进行参数赋值,而复杂变量类型无法直接通过字节码读取的方式进行参数赋值。然后,获取将复杂变量类型转换为基本变量类型的转换代码,结合该转换代码,将测试参数中的复杂变量类型对应的测试参数转换给包括至少一种基本变量类型对应的测试参数,其中,一种基本变量类型的情况可以为:某一复杂变量类型对应的测试参数由多个相同数据类型的基本变量类型构成。
可选地,基于参数拆解方式将复杂变量类型对应的测试参数通过遍历算法,如:深度优先遍历算法、广度优先遍历算法,解析为包含基本变量类型的测试参数,再根据这些基本变量类型的数据类型,获得复杂变量类型对应的测试参数的转换代码。
本公开通过基于参数拆解生成测试驱动代码,将复杂变量类型对应的测试参数转换为基本变量类型对应的测试参数,继而基于获得的转换代码将所有测试参数转换为通用字节码格式,以便基于通用字节码格式的参数进行模糊测试。
字节码(list<byte>)是一种包含执行程序、由一序列op(操作码)代码/数据对组成的二进制文件,字节码是一种中间码,经常被看作是包含一个执行程序的二进制文件,字节码由于被预处理过,所以比一般的解释代码要快。
本方案提供的转换代码为测试驱动代码的一部分,利用转换代码进行格式转换后的测试参数能够通过字节码读取的方式进行参数赋值,以保证测试过程的顺利进行,而且,有利于提升测试数据的全面性及测试效果。
进一步地,通过测试驱动代码将通用字节码格式的测试参数之后,进行正确的参数调用。通过这种方式实现测试参数读取、调用,即实现对测试过程中测试函数的参数赋值。
本实施例提供的方案,在进行模糊测试之前,在测试驱动代码中加入了参数格式的转换并相应调整了新增代码段的参数调用,避免参数格式引起的测试过程无法继续进行的问题,保证程序测试过程的顺利进行。
在一种可行的实施例中,S130的利用所述测试驱动代码对所述程序代码进行模糊测试的步骤,包括:
创建临时目录作为模糊测试的工作路径,在所述工作路径下调用程序模糊测试工具进行模糊测试。
创建临时目录作为模糊测试的工作路径,以免污染待测试程序项目所在的文件目录,将创建的临时目录作为工作路径,在该工作路径下只进行程序测试,避免将待测试程序项目与测试项目置于一个工作路径,导致文件数据量较大,避免文件数据量大造成的数据混乱及访问效率低下等问题。
可选地,在模糊测试过程中,监测模糊测试时长,检测到模糊测试时长超出预先设置的测试时长时,中断该次模糊测试,以控制测试时长,避免对计算资源的过度抢占。
进一步地,模糊测试完成后,将检测的代码错误结果进行汇总,结合代码错误位置去重并上报服务器,输出代码错误检测报告。
下面结合实际中进行的测试阐述本公开提供的测试方法的效果:
待测试程序为开源程序项目jsonparser(地址为https://github.com/buger/jsonparser),该程序项目在代码托管网站Github上有超过3千的收藏量,项目描述是“Go语言最快的不需要模式的替代JSON解析器”。利用本公开提供的方案进行程序测试,在这个开源包的4个开放调用接口处发现8处代码错误,这些代码错误会导致程序崩溃甚至死循环,以下做详细介绍。
本次程序测试的配置信息如下:针对版本号为1a2960的4)jsonparser程序项目进行测试,待测函数的筛选条件为:对jsonparser的14个开放调用接口进行自动化模糊测试,这14个开放调用接口分别是:Delete、Get、GetBoolean、GetFloat、GetInt、GetString、GetUnsafeString、ParseBoolean、ParseFloat、ParseInt、ParseString、Set、StringToBytes、Unescape,每个开放调用接口设置的测试时长为300秒,并根据代码错误位置对测试结果进行去重处理。
通过本公开提供的程序测试方法进行测试后的测试结果如下:在4个开放接口中发现了8个代码错误,具体地,如下4个接口中每个接口均发现2个代码错误:Delete、Get、GetBoolean、Set。代码错误类型中包括:2例死循环、4例数组索引越界、2例切片索引错误,其中死循环的程序漏洞,如果被利用,可能会导致服务器拒绝服务等严重的安全事故。
如下这段程序中出现了死循环:
这段程序调用Delete接口,程序执行时会掉入死循环,即代码执行不会结束,造成计算资源浪费,甚至导致服务器拒绝服务等严重的安全事故。使用本发明所述方法,成功发现该处代码错误,而该问题此前未被公开披露。目前已得到开发者确认并进行修复。
如下这段程序出现数组下标越界,程序如下:
这段程序同样是调用Delete接口,程序执行时由于切片索引错误的代码错误,导致运行崩溃。使用本公开提供的测试方法,成功发现该处代码错误,而该问题此前未被公开披露。
进一步地,本公开实施例还提供了一种可能的实现方式,如图5所示,提供了一种程序测试装置500,包括:获得关键信息模块510、生成测试驱动代码模块520、模糊测试模块530,具体如下:
获得关键信息模块510,用于对待测试程序的程序代码进行静态分析,获取所述程序代码中的待测函数,解析所述待测函数获得所述待测函数的关键信息;
生成测试驱动代码模块520,用于基于所述待测函数的关键信息生成用于驱动待测试程序进行测试的测试驱动代码;
模糊测试模块530,用于利用所述测试驱动代码对所述程序代码进行模糊测试,以确定待测试程序中的异常信息,所述异常信息包括:错误代码和安全漏洞。
本公开实施例的程序测试装置可执行本公开实施例所提供的一种程序测试方法,其实现原理相类似,本公开各实施例中的程序测试装置中的各模块所执行的动作是与本公开各实施例中的程序测试方法中的步骤相对应的,对于程序测试装置的各模块的详细功能描述具体可以参见前文中所示的对应的程序测试方法中的描述,此处不再赘述。
基于与本公开的实施例中所示的方法相同的原理,本公开的实施例中还提供了一种电子设备,该电子设备可以包括但不限于:处理器和存储器;存储器,用于存储计算机操作指令;处理器,用于通过调用计算机操作指令执行实施例所示的程序测试方法。与现有技术相比,本公开提供的程序测试方法,基于测试驱动代码对所述程序代码进行模糊测试,实现对错误代码及安全漏洞的检测,在该测试过程中,无需依赖人工编写测试的驱动函数,或人工编写测试输入样例,大大提高了测试过程的自动化程度,实现全流程自动化的程序自动化模糊测试,有利于实现模糊测试技术的大规模、自动化应用。
在一个可选实施例中提供了一种电子设备,如图6所示,图6所示的电子设备4000可以为服务器端,包括:处理器4001和存储器4003。其中,处理器4001和存储器4003相连,如通过总线4002相连。可选地,电子设备4000还可以包括收发器4004。需要说明的是,实际应用中收发器4004不限于一个,该电子设备4000的结构并不构成对本公开实施例的限定。
处理器4001可以是CPU(Central Processing Unit,中央处理器),通用处理器,DSP(Digital Signal Processor,数据信号处理器),ASIC(Application SpecificIntegrated Circuit,专用集成电路),FPGA(Field Programmable Gate Array,现场可编程门阵列)或者其他可编程逻辑器件、晶体管逻辑器件、硬件部件或者其任意组合。其可以实现或执行结合本公开公开内容所描述的各种示例性的逻辑方框,模块和电路。处理器4001也可以是实现计算功能的组合,例如包含一个或多个微处理器组合,DSP和微处理器的组合等。
总线4002可包括一通路,在上述组件之间传送信息。总线4002可以是PCI(Peripheral Component Interconnect,外设部件互连标准)总线或EISA(ExtendedIndustry Standard Architecture,扩展工业标准结构)总线等。总线4002可以分为地址总线、数据总线、控制总线等。为便于表示,图6中仅用一条粗线表示,但并不表示仅有一根总线或一种类型的总线。
存储器4003可以是ROM(Read Only Memory,只读存储器)或可存储静态信息和指令的其他类型的静态存储设备,RAM(Random Access Memory,随机存取存储器)或者可存储信息和指令的其他类型的动态存储设备,也可以是EEPROM(Electrically ErasableProgrammable Read Only Memory,电可擦可编程只读存储器)、CD-ROM(Compact DiscRead Only Memory,只读光盘)或其他光盘存储、光碟存储(包括压缩光碟、激光碟、光碟、数字通用光碟、蓝光光碟等)、磁盘存储介质或者其他磁存储设备、或者能够用于携带或存储具有指令或数据结构形式的期望的程序代码并能够由计算机存取的任何其他介质,但不限于此。
存储器4003用于存储执行本公开方案的应用程序代码,并由处理器4001来控制执行。处理器4001用于执行存储器4003中存储的应用程序代码,以实现前述方法实施例所示的内容。
其中,电子设备包括但不限于:移动电话、笔记本电脑、数字广播接收器、PDA(个人数字助理)、PAD(平板电脑)、PMP(便携式多媒体播放器)、车载终端(例如车载导航终端)等等的移动终端以及诸如数字TV、台式计算机等等的固定终端。图6示出的电子设备仅仅是一个示例,不应对本公开实施例的功能和使用范围带来任何限制。
本公开实施例提供了一种计算机可读存储介质,该计算机可读存储介质上存储有计算机程序,当其在计算机上运行时,使得计算机可以执行前述方法实施例中相应内容。
应该理解的是,虽然附图的流程图中的各个步骤按照箭头的指示依次显示,但是这些步骤并不是必然按照箭头指示的顺序依次执行。除非本文中有明确的说明,这些步骤的执行并没有严格的顺序限制,其可以以其他的顺序执行。而且,附图的流程图中的至少一部分步骤可以包括多个子步骤或者多个阶段,这些子步骤或者阶段并不必然是在同一时刻执行完成,而是可以在不同的时刻执行,其执行顺序也不必然是依次进行,而是可以与其他步骤或者其他步骤的子步骤或者阶段的至少一部分轮流或者交替地执行。
需要说明的是,本公开上述的计算机可读介质可以是计算机可读信号介质或者计算机可读存储介质或者是上述两者的任意组合。计算机可读存储介质例如可以是——但不限于——电、磁、光、电磁、红外线、或半导体的***、装置或器件,或者任意以上的组合。计算机可读存储介质的更具体的例子可以包括但不限于:具有一个或多个导线的电连接、便携式计算机磁盘、硬盘、随机访问存储器(RAM)、只读存储器(ROM)、可擦式可编程只读存储器(EPROM或闪存)、光纤、便携式紧凑磁盘只读存储器(CD-ROM)、光存储器件、磁存储器件、或者上述的任意合适的组合。在本公开中,计算机可读存储介质可以是任何包含或存储程序的有形介质,该程序可以被指令执行***、装置或者器件使用或者与其结合使用。而在本公开中,计算机可读信号介质可以包括在基带中或者作为载波一部分传播的数据信号,其中承载了计算机可读的程序代码。这种传播的数据信号可以采用多种形式,包括但不限于电磁信号、光信号或上述的任意合适的组合。计算机可读信号介质还可以是计算机可读存储介质以外的任何计算机可读介质,该计算机可读信号介质可以发送、传播或者传输用于由指令执行***、装置或者器件使用或者与其结合使用的程序。计算机可读介质上包含的程序代码可以用任何适当的介质传输,包括但不限于:电线、光缆、RF(射频)等等,或者上述的任意合适的组合。
上述计算机可读介质可以是上述电子设备中所包含的,也可以是单独存在,而未装配入该电子设备中。
上述计算机可读介质承载有一个或者多个程序,当上述一个或者多个程序被该电子设备执行时,使得该电子设备执行上述实施例所示的方法的步骤。
可以采用一种或多种程序设计语言或其组合来编写用于执行本公开的操作的计算机程序代码,上述程序设计语言包括面向对象的程序设计语言—诸如Java、Smalltalk、C++,还包括常规的过程式程序设计语言—诸如“C”语言或类似的程序设计语言。程序代码可以完全地在用户计算机上执行、部分地在用户计算机上执行、作为一个独立的软件包执行、部分在用户计算机上部分在远程计算机上执行、或者完全在远程计算机或服务器上执行。在涉及远程计算机的情形中,远程计算机可以通过任意种类的网络——包括局域网(LAN)或广域网(WAN)—连接到用户计算机,或者,可以连接到外部计算机(例如利用因特网服务提供商来通过因特网连接)。
附图中的流程图和框图,图示了按照本公开各种实施例的***、方法和计算机程序产品的可能实现的体系架构、功能和操作。在这点上,流程图或框图中的每个方框可以代表一个模块、程序段、或代码的一部分,该模块、程序段、或代码的一部分包含一个或多个用于实现规定的逻辑功能的可执行指令。也应当注意,在有些作为替换的实现中,方框中所标注的功能也可以以不同于附图中所标注的顺序发生。例如,两个接连地表示的方框实际上可以基本并行地执行,它们有时也可以按相反的顺序执行,这依所涉及的功能而定。也要注意的是,框图和/或流程图中的每个方框、以及框图和/或流程图中的方框的组合,可以用执行规定的功能或操作的专用的基于硬件的***来实现,或者可以用专用硬件与计算机指令的组合来实现。
描述于本公开实施例中所涉及到的模块可以通过软件的方式实现,也可以通过硬件的方式来实现。其中,模块的名称在某种情况下并不构成对该模块本身的限定,例如,获得关键信息模块还可以被描述为“获得待测函数的关键信息模块”。
根据本公开的一个或多个实施例,提供了一种程序测试方法,包括:
对待测试程序的程序代码进行静态分析,获取所述程序代码中的待测函数,解析所述待测函数获得所述待测函数的关键信息;
基于所述待测函数的关键信息生成用于驱动待测试程序进行测试的测试驱动代码;
利用所述测试驱动代码对所述程序代码进行模糊测试,以确定待测试程序中的异常信息,所述异常信息包括:错误代码和安全漏洞中的至少一个。
可选地,所述对待测试程序的程序代码进行静态分析之后,还包括:
将所述程序代码划分为多个基本块;所述基本块是程序diam中顺序执行且仅有一个出入口的语句序列;
在每个所述基本块中***用于统计覆盖率信息的代码;
所述利用所述测试驱动代码对所述程序代码进行模糊测试,包括:
利用所述统计覆盖率信息的代码及所述测试驱动代码对所述程序代码进行模糊测试。
可选地,所述对待测试程序的程序代码进行静态分析之后,还包括:
获得所述程序代码的安全关键位置;
在所述安全关键位置处***用于安全属性检查的代码;
所述利用所述测试驱动代码对所述程序代码进行模糊测试,包括:
利用所述安全属性检查的代码及所述测试驱动代码对所述程序代码进行模糊测试。
可选地,在所述安全关键位置处***用于安全属性检查的代码,包括:
获取预先集成的多种针对不同代码安全问题的安全属性规则;
获取程序代码的抽象语法树,并对所述抽象语法树进行污点分析,获得抽象语法树上各代码安全关键位置处的代码安全问题;
在代码安全关键位置处***与该位置处的代码安全问题相匹配的安全属性规则的代码。
可选地,所述对待测试程序的程序代码进行静态分析,获取所述程序代码中的待测函数,解析所述待测函数获得所述待测函数的关键信息的步骤,包括:
基于程序测试的场景信息确定函数的筛选条件,利用所述筛选条件从所述程序代码对应的函数中筛选出待测函数;
解析所述待测函数获得其中的关键信息,所述关键信息包括参数列表、参数类型、参数内部构成中的至少一个。
可选地,所述基于所述待测函数的关键信息生成测试驱动代码,包括:
根据所述关键信息中的参数类型将待测函数划分为基本待测函数和复杂待测函数;
依据预设的测试驱动规则对所述复杂待测函数进行规则匹配,并根据与所述复杂待测函数相匹配的测试驱动规则对应的处理逻辑来处理所述复杂待测函数的关键信息,生成测试驱动代码。
可选地,所述生成测试驱动代码之前,还包括:
获取用于进行程序测试的测试参数,对所述测试参数进行参数信息分析,获得各测试参数的数据类型;
根据所述数据类型将所述测试参数划分为基本变量类型对应的测试参数及复杂变量类型对应的测试参数;其中,基本变量类型对应的测试参数能够在模糊测试中通过字节码读取的方式进行参数赋值;
确定测试驱动代码中将复杂变量类型对应的测试参数转换为基本变量类型的转换代码,以利用所述转换代码将所述复杂变量类型对应的测试参数解析为由至少一种基本变量类型构成的参数。
可选地,所述利用所述测试驱动代码对所述程序代码进行模糊测试,包括:
创建临时目录作为模糊测试的工作路径,在所述工作路径下调用程序模糊测试工具进行模糊测试。
根据本公开的一个或多个实施例,还提供了一种程序测试装置,该装置包括:
获得关键信息模块,用于对待测试程序的程序代码进行静态分析,获取所述程序代码中的待测函数,解析所述待测函数获得所述待测函数的关键信息;
生成测试驱动代码模块,用于基于所述待测函数的关键信息生成用于驱动待测试程序进行测试的测试驱动代码;
模糊测试模块,用于利用所述测试驱动代码对所述程序代码进行模糊测试,以确定待测试程序中的异常信息,所述异常信息包括:错误代码和安全漏洞中的至少一个。
可选地,程序测试装置,还包括:
基本块模块,用于将所述程序代码划分为多个基本块;
***覆盖率统计代码模块,用于在每个所述基本块中***用于统计覆盖率信息的代码;
模糊测试模块,还用于利用所述统计覆盖率信息的代码及所述测试驱动代码对所述程序代码进行模糊测试。
可选地,程序测试装置,还包括:
获得关键位置模块,用于获得所述程序代码的安全关键位置;
***安全属性检查模块,用于在所述安全关键位置处***用于安全属性检查的代码;
模糊测试模块,还用于利用所述安全属性检查的代码及所述测试驱动代码对所述程序代码进行模糊测试。
可选地,***模块,还包括:
获取安全属性规则单元,用于获取预先集成的多种针对不同代码安全问题的安全属性规则;
获得代码安全问题单元,用于获取程序代码的抽象语法树,并对所述抽象语法树进行污点分析,获得抽象语法树上各代码安全关键位置处的代码安全问题;
***安全属性代码单元,用于在代码安全关键位置处***与该位置处的代码安全问题相匹配的安全属性规则的代码。
可选地,获得关键信息模块,包括:
筛选待测函数单元,用于基于程序测试的场景信息确定函数的筛选条件,利用所述筛选条件从所述程序代码对应的函数中筛选出待测函数;
解析单元,用于解析所述待测函数获得其中的关键信息,所述关键信息包括参数列表、参数类型、参数内部构成中的至少一个。
可选地,生成测试驱动代码模块,包括:
划分单元,用于根据所述关键信息中的参数类型将待测函数划分为基本待测函数和复杂待测函数;
规则匹配单元,用于依据预设的测试驱动规则对所述复杂待测函数进行规则匹配,并根据与所述复杂待测函数相匹配的测试驱动规则对应的处理逻辑来处理所述复杂待测函数的关键信息,生成测试驱动代码。
可选地,生成测试驱动代码模块,还包括:
获取参数单元,用于获取用于进行程序测试的测试参数,对所述测试参数进行参数信息分析,获得各测试参数的数据类型;
划分单元,用于根据所述数据类型将所述测试参数划分为基本变量类型对应的测试参数及复杂变量类型对应的测试参数;其中,基本变量类型对应的测试参数能够在模糊测试中通过字节码读取的方式进行参数赋值;
解析参数单元,用于遍历所述参数的数据结构,将复杂参数解析为包括至少一种基本变量类型的参数;
转换单元,用于确定测试驱动代码中将复杂变量类型转换为基本变量类型的转换代码,以利用所述转换代码将所述复杂变量类型对应的测试参数解析为由至少一种基本变量类型构成的参数;
可选地,模糊测试模块,还用于创建临时目录作为模糊测试的工作路径,在所述工作路径下调用程序模糊测试工具进行模糊测试。
以上描述仅为本公开的较佳实施例以及对所运用技术原理的说明。本领域技术人员应当理解,本公开中所涉及的公开范围,并不限于上述技术特征的特定组合而成的技术方案,同时也应涵盖在不脱离上述公开构思的情况下,由上述技术特征或其等同特征进行任意组合而形成的其它技术方案。例如上述特征与本公开中公开的(但不限于)具有类似功能的技术特征进行互相替换而形成的技术方案。
此外,虽然采用特定次序描绘了各操作,但是这不应当理解为要求这些操作以所示出的特定次序或以顺序次序执行来执行。在一定环境下,多任务和并行处理可能是有利的。同样地,虽然在上面论述中包含了若干具体实现细节,但是这些不应当被解释为对本公开的范围的限制。在单独的实施例的上下文中描述的某些特征还可以组合地实现在单个实施例中。相反地,在单个实施例的上下文中描述的各种特征也可以单独地或以任何合适的子组合的方式实现在多个实施例中。尽管已经采用特定于结构特征和/或方法逻辑动作的语言描述了本主题,但是应当理解所附权利要求书中所限定的主题未必局限于上面描述的特定特征或动作。相反,上面所描述的特定特征和动作仅仅是实现权利要求书的示例形式。