CN111367786B - 一种符号执行方法、电子设备以及存储介质 - Google Patents
一种符号执行方法、电子设备以及存储介质 Download PDFInfo
- Publication number
- CN111367786B CN111367786B CN201811602959.7A CN201811602959A CN111367786B CN 111367786 B CN111367786 B CN 111367786B CN 201811602959 A CN201811602959 A CN 201811602959A CN 111367786 B CN111367786 B CN 111367786B
- Authority
- CN
- China
- Prior art keywords
- child node
- execution
- node
- code
- constraint condition
- Prior art date
- Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
- Active
Links
Images
Classifications
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F11/00—Error detection; Error correction; Monitoring
- G06F11/36—Preventing errors by testing or debugging software
- G06F11/3668—Software testing
- G06F11/3672—Test management
- G06F11/3688—Test management for test execution, e.g. scheduling of test suites
Landscapes
- Engineering & Computer Science (AREA)
- Theoretical Computer Science (AREA)
- Computer Hardware Design (AREA)
- Quality & Reliability (AREA)
- Physics & Mathematics (AREA)
- General Engineering & Computer Science (AREA)
- General Physics & Mathematics (AREA)
- Debugging And Monitoring (AREA)
Abstract
本发明实施例公开了一种符号执行方法、电子设备以及存储介质,所述方法包括确定代码基本块,根据所述父节点确定初始定义数据、第一约束条件以及第二约束条件,根据所述第一子节点对所述初始定义数据进行携带所述第一约束条件的赋值操作以生成第一存储数据集合,根据所述第二子节点对所述初始定义数据进行携带所述第二约束条件的赋值操作以生成第二存储数据集合。采用本方面所示的符号执行的方法所示可知,在无需对路径进行合并以及复制的操作,即可一次完成对所述代码基本块所包括的所有路径的遍历,提高了对被测试代码所包括的路径进行遍历的效率。
Description
技术领域
本发明实施例涉及计算机技术领域,尤其涉及的是一种符号执行方法、电子设备以及存储介质。
背景技术
符号执行技术是应用程序分析与测试的一种重要技术手段,在20世纪70年代被提出,但由于一些技术难点未克服,符号执行在之后相当长的时间里基本停留于理论研究和简单测试样例上。近几年得益于求解器性能大幅提升,符号执行技术得到了重新青睐,相关的学术研究和工业实践数量也呈高速增长态势。
符号执行技术中的一次测试回合里,应用程序的输入值不是确定的,而是未知的,称为符号值。我们称这种执行方式叫符号执行,由于输入是未知量,所以在遇到应用程序分支时,符号执行引擎会判断分支的可行性,并将可行的路径加入路径约束集合,并纪录路径约束。路径约束的含义是对能够使应用程序进入当前路径的符号值的约束,所以一条路径执行完毕后可以求解它的路径约束,得到进入该路径的一个真实用例。如此下去理论上将会遍历应用程序所有可达路径。每深入应用程序的一层,路径约束集合的大小将增加,同时路径的个数也将增加。
因符号执行技术是用未知的符号值来代替实际值并进行遍历执行探索的应用程序测试技术,理论上可以遍历应用程序中所有可达路径。但实际中,应用程序的可能执行路径空间的数量很可能是天文数字,导致符号执行引擎资源耗尽而不可用,我们称之为路径爆炸,在路径爆炸的情况下,在有限的时间消耗和资源消耗内,无法完成对应用程序的有效分析。
发明内容
本发明提供一种能够有效的缓解路径爆炸的一种符号执行方法、电子设备以及存储介质。
本发明实施例第一方面提供了一种符号执行方法,包括:
步骤A、符号执行引擎确定代码基本块。
本实施例所示的符号执行引擎可对存储器所运行的需要进行测量的被测试代码进行遍历以识别出被测试代码所包括的各代码基本块,且所述代码基本块具有单一入口以及单一出口,且该代码基本块的出口包括但不限于函数调用、约束、分支等等,只要代码基本块使应用程序的代码逻辑上不再连续的操作即可。
具体的,所述代码基本块包括父节点、第一子节点、第二子节点以及结束节点,在对所述代码基本块进行遍历时,所述代码执行引擎可确定出所述代码基本块所对应的预设代码执行顺序,所述预设代码执行顺序包括第一执行路径以及第二执行路径,所述第一执行路径按代码执行顺序依次降低的排序依次包括所述父节点、所述第一子节点和所述结束节点,所述第二执行路径按代码执行顺序依次降低的排序依次包括所述父节点、所述第二子节点和所述结束节点,且所述第一子节点和所述第二子节点之间无代码执行的先后顺序;
步骤B、符号执行引擎执行所述父节点。
在所述符合执行引擎执行所述父节点后,即可根据所述父节点确定初始定义数据、第一约束条件以及第二约束条件,所述初始定义数据为输入至所述代码基本块的数据,所述第一约束条件为执行所述第一子节点的条件,所述第二约束条件为执行所述第二子节点的条件。
步骤C、符号执行引擎执行所述第一子节点。
具体的,所述符号执行引擎可在执行所述第一子节点的过程中,根据所述第一子节点对所述初始定义数据进行携带所述第一约束条件的赋值操作以生成第一存储数据集合,所述第一存储数据集合用于指示,在所述初始定义数据满足所述第一约束条件时,根据所述第一子节点所定义的数据对所述初始定义数据进行赋值,在所述初始定义数据不满足所述第一约束条件时,则所述初始定义数据保持不变。
步骤D、符号执行引擎执行所述第二子节点。
具体的,所述符号执行引擎可在执行所述第二子节点的过程中,根据所述第二子节点对所述初始定义数据进行携带所述第二约束条件的赋值操作以生成第二存储数据集合,所述第二存储数据集合用于指示,在所述初始定义数据满足所述第二约束条件时,根据所述第二子节点所定义的数据对所述初始定义数据进行赋值,在所述初始定义数据不满足所述第二约束条件时,则根据所述第一存储数据集合对所述初始定义数据进行赋值。
步骤E、符号执行引擎执行所述结束节点。
所述符号执行引擎执行所述结束节点后,所述符号执行引擎即可确定出对所述代码基本块执行完毕。
采用本方面所示的符号执行的方法所示可知,在符号执行过程中,无论初始定义数据具体的取值为何,所述符号执行引擎均可遍历所述代码基本块所包括的任一路径,而且在遍历所述代码基本块所包括的任一路径的过程中,无需对代码基本块所包括的路径进行复制以及合并的操作,只要在执行第一子节点时,符号执行引擎根据所述第一子节点对所述初始定义数据进行携带所述第一约束条件的赋值操作即可,在执行第二子节点时,符号执行引擎根据所述第二子节点对所述初始定义数据进行携带所述第二约束条件的赋值操作即可,可见,在代码基本块中,将原先并列执行的第一子节点和第二子节点更改为先后执行的两个子节点,所述符号执行引擎即可携带第一约束条件以及携带第二约束条件的赋值操作,在无需对路径进行合并以及复制的操作,即可一次完成对所述代码基本块所包括的所有路径的遍历,提高了对被测试代码所包括的路径进行遍历的效率。
结合本发明实施例的第一方面,本发明实施例的第一方面的一种可选的实现方式中,所述步骤C具体用于执行如下所示的步骤:
步骤C11、符号执行引擎获取所述第一子节点所定义的数据。
步骤C12、符号执行引擎生成所述第一存储数据集合。
具体的,所述第一存储数据集合可通过条件选择算符的方式进行表达,即所述第一存储数据集合=ite{第一约束条件,第一子节点所定义的数据,初始定义数据},所述第一存储数据集合用于指示,在所述初始定义数据满足所述第一约束条件时,根据所述第一子节点所定义的数据对所述初始定义数据进行赋值,在所述初始定义数据不满足所述第一约束条件时,则所述初始定义数据保持不变。
结合本发明实施例的第一方面,本发明实施例的第一方面的一种可选的实现方式中,所述步骤D具体用于执行如下所示的步骤:
步骤D11、符号执行引擎获取所述第二子节点所定义的数据;
步骤D12、符号执行引擎生成所述第二存储数据集合。
具体的,所述第二存储数据集合可通过条件选择算符的方式进行表达,所述第二存储数据集合=ite{第二约束条件,第二子节点所定义的数据,第一存储数据集合},所述第二存储数据集合用于指示,在所述初始定义数据满足所述第二约束条件时,根据所述第二子节点所定义的数据对所述初始定义数据进行赋值,在所述初始定义数据不满足所述第二约束条件时,根据所述第一存储数据集合对所述初始定义数据进行赋值。
结合本发明实施例的第一方面,本发明实施例的第一方面的一种可选的实现方式中,所述步骤A之后,还包括如下步骤:
步骤A11、符号执行引擎确定执行树。
所述执行树包括所述父节点、所述第一子节点、所述第二子节点以及所述结束节点,所述执行树所包括的所述父节点、所述第一子节点、所述第二子节点以及所述结束节点的代码执行顺序依次降低。
采用本方面所示的方法,所述符号执行引擎基于所述执行树对代码基本块进行测试号,从而使得原先由并列执行的第一子节点和第二子节点更改为先后执行的顺序,可见,本方面所示的符号执行方法无需被测试代码的路径的复制与合并操作,本实施例所示的方法只需要只跟踪所述执行树所示的一条程序路径,在遇到条件分支时不进行态复制,只需要进行携带约束条件的赋值操作即可,可见,在不改变被测试代码的机制的基础上实现,有效的提高了路径遍历的效率。
结合本发明实施例的第一方面,本发明实施例的第一方面的一种可选的实现方式中,所述步骤C之后,还包括如下步骤:
步骤C21、符号执行引擎将所述第一存储数据集合写入至内存,以使所述内存的存储状态值为所述第一存储数据集合。
结合本发明实施例的第一方面,本发明实施例的第一方面的一种可选的实现方式中,所述步骤D之后,还包括如下步骤:
步骤D21、符号执行引擎将所述第二存储数据集合写入至所述内存,以使所述内存的存储状态值为所述第二存储数据集合。
采用本方面所示的方法,无需进行路径符合与合并的操作的情况下,即可实现对代码基本块所包括的所有路径的逻辑信息的完整收集,有效的省去了路径复制与合并时的额外开销,效率得到提升。
结合本发明实施例的第一方面,本发明实施例的第一方面的一种可选的实现方式中,所述第一子节点以及所述第二子节点中,有1个或0个为空。
本方面实施例第二方面提供了一种电子设备,包括:
确定单元,用于确定代码基本块,所述代码基本块包括父节点、第一子节点、第二子节点以及结束节点,所述代码基本块的预设代码执行顺序包括第一执行路径以及第二执行路径,所述第一执行路径按代码执行顺序依次降低的排序依次包括所述父节点、所述第一子节点和所述结束节点,所述第二执行路径按代码执行顺序依次降低的排序依次包括所述父节点、所述第二子节点和所述结束节点,且所述第一子节点和所述第二子节点之间无代码执行的先后顺序;
第一执行单元,用于根据所述父节点确定初始定义数据、第一约束条件以及第二约束条件,所述第一约束条件为执行所述第一子节点的条件,所述第二约束条件为执行所述第二子节点的条件;
第二执行单元,用于根据所述第一子节点对所述初始定义数据进行携带所述第一约束条件的赋值操作以生成第一存储数据集合,所述第一存储数据集合包括所述第一约束条件、所述第一子节点所定义的数据以及所述初始定义数据;
第三执行单元,用于根据所述第二子节点对所述初始定义数据进行携带所述第二约束条件的赋值操作以生成第二存储数据集合,所述第二存储数据集合包括所述第二约束条件、所述第二子节点所定义的数据以及所述第一存储数据集合。
本方面所示的电子设备执行符号执行方法的具体过程以及有益效果的说明,请详见上述第一方面所示,具体不做赘述。
结合本发明实施例的第二方面,本发明实施例的第二方面的一种可选的实现方式中,所述第二执行单元包括:
第一获取模块,用于获取所述第一子节点所定义的数据;
第一生成模块,用于生成所述第一存储数据集合,所述第一存储数据集合用于指示,在所述初始定义数据满足所述第一约束条件时,根据所述第一子节点所定义的数据对所述初始定义数据进行赋值,在所述初始定义数据不满足所述第一约束条件时,所述初始定义数据保持不变。
结合本发明实施例的第二方面,本发明实施例的第二方面的一种可选的实现方式中,所述第三执行单元包括:
第二获取模块,用于获取所述第二子节点所定义的数据;
第二生成模块,用于生成所述第二存储数据集合,所述第二存储数据集合用于指示,在所述初始定义数据满足所述第二约束条件时,根据所述第二子节点所定义的数据对所述初始定义数据进行赋值,在所述初始定义数据不满足所述第二约束条件时,根据所述第一存储数据集合对所述初始定义数据进行赋值。
结合本发明实施例的第二方面,本发明实施例的第二方面的一种可选的实现方式中,所述确定单元还用于,确定执行树,所述执行树包括所述父节点、所述第一子节点、所述第二子节点以及所述结束节点,所述执行树所包括的所述父节点、所述第一子节点、所述第二子节点以及所述结束节点的代码执行顺序依次降低。
结合本发明实施例的第二方面,本发明实施例的第二方面的一种可选的实现方式中,所述第二执行单元还用于,将所述第一存储数据集合写入至内存,以使所述内存的存储状态值为所述第一存储数据集合。
结合本发明实施例的第二方面,本发明实施例的第二方面的一种可选的实现方式中,所述第三执行单元还用于,将所述第二存储数据集合写入至所述内存,以使所述内存的存储状态值为所述第二存储数据集合。
结合本发明实施例的第二方面,本发明实施例的第二方面的一种可选的实现方式中,所述第一存储数据集合以条件选择算符的方式存储于所述内存中,所述第二存储数据集合以条件选择算符的方式存储于所述内存中。
结合本发明实施例的第二方面,本发明实施例的第二方面的一种可选的实现方式中,所述第一子节点以及所述第二子节点中,有1个或0个为空。
本发明第三方面提供了一种电子设备,包括处理器和存储器,其中,
所述存储器中存有计算机程序产品;
所述处理器通过运行所述存储器中的所述计算机程序产品,以用于完成上述第一方面所示的符号执行方法。
本方面所示的电子设备执行符号执行方法的具体过程以及有益效果的说明,请详见上述第一方面所示,具体不做赘述。
本发明第四方面提供了一种计算机程序产品,当所述计算机产品被执行时,其用于执行上述第一方面所示的符号执行方法。
本发明第五方面提供了一种计算机可读存储介质,所述计算机可读存储介质中存储有指令,所述指令用于执行上述第一方面所示的符号执行方法。
附图说明
图1为本发明所提供的电子设备的一种实施例结构示意图;
图2为现有技术所示的符号执行方法的一种代码逻辑示例图;
图3为现有技术所示的符号执行方法的另一种代码逻辑示例图;
图4为现有技术所示的符号执行方法的另一种代码逻辑示例图;
图5为本发明所示的符号执行方法的一种实施例步骤流程图;
图6为本发明所提供的代码基本块的预设代码执行顺序的示例图;
图7为一种代码逻辑示例图;
图8为另一种代码逻辑示例图;
图9为本发明所提供的代码基本块代码一种执行顺序的示例图;
图10为本发明所提供的代码基本块代码另一种执行顺序的示例图;
图11为本发明所提供的代码基本块的执行树的一种结构示例图;
图12为本发明所提供的代码基本块的一种逻辑流程示例图;
图13为本发明所提供的电子设备的一种实施例结构示意图。
具体实施方式
本发明实施例提供了一种能够有效缓解路径爆炸的符号执行方法,为更好的理解本实施了所示的所示符号执行方法,以下首先结合图1所示对本实施了所示的方法所应用的电子设备的结构进行示例性说明:
图1是本发明实施例提供的一种电子设备的结构示意图,该电子设备100可因配置或性能不同而产生比较大的差异,可以包括一个或一个以上处理器122,一个或一个以上存储应用程序142的存储器130(例如一个或一个以上海量存储设备)。
其中,所述处理器122可为中央处理器(central processing units,CPU),或为微处理器,或为特定应用集成电路(application-specific integrated circuit,ASIC),或为一个或多个用于控制执行本实施例所示的符号执行方法的集成电路。所述存储器130可以是短暂存储或持久存储。存储在存储器130的应用程序可以包括一个或一个以上模块(图示没标出),每个模块可以包括对电子设备中的一系列指令操作。更进一步地,处理器122可以设置为与存储器130通信,在电子设备100上执行存储器130中的一系列指令操作。本实施例所示的应用程序142,所述存储器130还包括符号执行引擎145,所示符号执行引擎145可用于对应用程序142通过符号执行技术进行测试。
具体的,测试者通过监控被测的应用程序142的实际运行状态来提取异常。测试者可以自定义监控的粒度,比如黑盒测试就是仅仅观察应用程序142整体的异常行为(死锁、崩溃等等),而灰盒测试会以应用程序142所包括的代码块者更小的指令粒度进行监控。很显然,在符号执行技术中,由于操作系统并没有提供使用符号值运行的环境,所以符号执行测试的应用程序是运行在专门建造的符号执行引擎145中的,监控的工作也在符号执行引擎145中实现。所以符号执行一般是一种虚拟机执行,符号执行引擎145可以完全掌握符号执行应用程序的运行逻辑。符号执行技术的理论成熟,可以进行安全测试(如潜在异常检测、应用程序遍历用例生成),功能测试(如逻辑验证、模型验证)等等多种任务。
电子设备100还可以包括一个或一个以上电源126,一个或一个以上有线或无线网络接口150,一个或一个以上输入输出接口158,和/或,一个或一个以上操作系统141。
以下首先结合图2所示对符号执行的过程进行示例性说明:
如图2所示,在一次测试回合里,符号执行引擎输入至应用程序的为不确定的符号值。由于输入值是未知量,所以在遇到应用程序分支时,符号执行引擎会判断分支的可行性,并将可行的路径加入路径约束集合,并在路径约束集合中纪录路径约束,其中,路径约束的含义对是能够使应用程序进入当前路径的符号值的约束,所以一条路径执行完毕后可以求解这条路径的路径约束。如此下去理论上将会遍历应用程序所有可达路径。形象表示如图2所示,e1,e2,e3,e4代表程序分支,本实施例所示的程序分支可为判断条件,T代表真,F代表假。
在当前测试回合中,在遇到程序分支e1时,符号执行引擎会判断程序分支e1的可行性,并确定执行e1至e2之间的路径时的路径约束{T==e1},将路径约束{T==e1}记录在路径约束集合中,同理,在通过e1至e2之间的路径进入程序分支e2时,符号执行引擎会判断程序分支e2的可行性,并确定执行e2至e3之间的路径时的路径约束{T==e1,T==e2},将路径约束T==e2记录在路径约束集合中,以此类推,可见,符号执行引擎在测试图1所示的应用程序时,每深入应用程序的一层,路径约束集合的大小将增加,可执行的路径的个数也将增加。
因符号执行技术是用输入的符号值来代替实际值并进行遍历执行探索的应用程序测试技术,理论上可以遍历应用程序中所有可达路径。但实际中,应用程序的可能执行路径空间的数量很可能是天文数字,导致符号执行引擎资源耗尽而不可用,我们称之为路径爆炸,下述对符号执行所示的路径爆炸的含义进行示例性说明,首先结合第一代码所示对路径爆炸进行示例性说明:
由上述第一代码所示可知,通过int foo定义了为返回整形值函数,通过int x定义了输入参数x为整形变量,在测试过程中,符号执行引擎可准备输入集合,所述输入集合包括有多个输入参数,例如,所述输入集合可为{1,3,100,3000,6789034}。符号执行引擎可将所述输入集合所包括的输入参数送给foo实际执行,第一代码的输入就是所述输入集合所包括的任一输入参数x。当遇到应用程序分支if(x>10)时,由于此时输入参数x可以是输入集合中的任意值,从而使得输入参数x有大于10的情况,也有小于或等于10的情况,进而使得在第一代码执行所述输入集合时,True==(x>10)和false==(x>10)的应用程序分支都是可行的;
具体例如,在所述输入参数x为3000时,第一代码执行该输入参数x时,执行True==(x>10)的应用程序分支,在所述输入参数x为3时,第一代码执行该输入参数x时,执行false==(x>10)的应用程序分支。
如第一代码return x+10所示,在符号执行引擎执行True==(x>10)的应用程序分支时,符号执行引擎通过foo函数将x+10带回调用处,再如第一代码return x-10所示,在符号执行引擎执行false==(x>10)的应用程序分支时,符号执行引擎通过foo函数将x–10带回调用处。
此时符号执行引擎将维护两条路径轨迹,即执行True==(x>10)的第一应用程序分支以及执行false==(x>10)的第二应用程序分支,所述符号执行引擎针对所述第一代码所包括的所有可行的路径分别配置路径约束集合,即针对第一应用程序分支设置第一路径约束集合,针对第二应用程序分支设置第二路径约束集合,所述符号执行引擎可将可执行的True==(x>10)的应用程序分支加入至所述第一路径约束集合中;符号执行引擎还可将可执行的false==(x>10)的应用程序分支加入至所述第二路径约束集合中。
第一代码所示的两条应用程序分支为实现应用程序的正常运行,则两条应用程序分支各自拥有完整的内存、变量等应用程序运行的资源,可见,True==(x>10)的应用程序分支以及执行false==(x>10)的应用程序分支同时并列的运行。
上述所示的第一代码的应用程序分支为一处,即判断条件if(x>10)为例进行示例性说明,在实际应用中,应用程序中的判断应用程序分支会有多处,则每深入应用程序一层,所述符号执行引擎所配置的所述路径约束集合所包括的路径约束的数量就会增加,同时可执行的路径的数量也将增加,因符号执行技术是用输入未知的符号值来代替实际值并进行遍历执行探索的应用程序测试技术,理论上可以遍历应用程序中所有可达路径。但实际中,应用程序的可能执行路径空间的数量很可能是天文数字,导致符号执行引擎资源耗尽而不可用,我们称之为路径爆炸,以下述所示的第二代码所示为例对路径爆炸进行示例性说明:
由上述所示的第二代码所示可知,通过int foo定义了为返回整形值函数,通过int x定义了输入参数x为整形变量以及通过int y定义了输入参数y为整形变量,通过inti定义i为整形变量,且i的循环初值为0;
while(i++<x)语句为判断分支语句,i++<x为循环条件,代码code 1为循环体,本实施例对code 1具体代码不做限定,即在执行while(i++<x)时,先执行判断分支语句,若为真则执行循环体,再循环执行判断分支语句,重复上述过程,直到判断分支语句为假时退出循环。退出循环后,若参数y==0x12345,则继续执行代码code 2,最后如第二代码return1所示,符号执行引擎通过foo函数将参数1带回调用处。
由于输入参数x可能取任意值,所以第一次运行时True==(0<x)的应用程序分支和false==(0<x)的应用程序分支皆可行,将产生两个路径分支,第一路分支路径执行路径约束为True==(0<x)的路径,第二路分支路径执行路径约束为false==(0<x)的路径,而True==(0<x)将在执行完code 1代码后再次回到判断分支语句while(i++<x)处进行第二次运行,在第二次运行时True==(1<x)的应用程序分支继续重复执行第一路分支路径,而在第二次运行时会产生新的分支路径,即第三分支路径,该第三分支路径的路径约束为false==(1<x),依次类推,可以推得循环n次后将产生n+1个路径可能性,其中1个态执行while循环的code 1片段,而其它n个路径跳过while循环继续向下执行。所以在while处将产生大量的路径约束集合。可以看到,当循环结构的结束点与符号值相关时,将有大量的路径产生。
而更严重的是,路径约束集合是呈指数增长的。若结束了第二代码所示的while的执行,此时有n个路径在维护。在if(y==0x12345)处,所有的路径都将复制成两份,因为该处的True和false分支都是可行的,所以经过该处判断后路径约束集合中的路径数量变为2*n,而不是n+1。M个True和false应用程序分支皆可行的分支语句将使已有的路径约束集合大小扩大2M倍。
针对实际运行的大型应用程序,符号执行引擎针对应用程序所配置的路径约束集合所包括的路径的数量是非常多的,所以实际大型应用程序中从头至尾使用符号执行的方式很容易会导致最终符号执行的不可用。
针对上述问题,现有技术提供了实际值和符号值结合(concrete and symbolic,concolic)技术,在concolic执行中,一次测试回合里输入的取值是确定的,于是执行的路径也仅仅是由该确定值所指引的一条路径。但同时输入的符号特性被保持,可以收集路径约束,所以在该路径上的分支点处求反即可得到使应用程序进入新的应用程序分支的输入值,接下来这些新得到的用例将作为下一轮concolic执行的输入值,如此迭代下去以遍历应用程序所有的路径,可以有效缓解路径爆炸,以下称这种concolic执行的方式为原始concolic执行方式。
以上述第一代码为例,假设原始concolic执行时使用符号值的取值为50,该输入值引导的路径执行的是if为True的应用程序分支,即(True==(x>10)。if判断处为与符号值相关的判断语句,所以在该处求反即可使得应用程序进入新的应用程序分支,即(false==(x>10)的应用程序分支,可见,对符号值50进行取反可以得到新的用例,比如x=8。接着8将作为新一轮concolic使用的具体输入值。显然,在concolic路径上若有N处判断语句,则最多可以产生N个新测试用例,则符号执行引擎就可以创建包括N个路径的路径约束集合,则可有效的降低路径约束集合所包括的路径的数量。
concolic模式只跟随由输入值所指引的路径,并在分支判断处求反以期得到能够进入新的应用程序分支的新用例。但实际上很多时候得到使应用程序进入新路径的输入值时会求解失败,即取反所得到的新的输入值不能够执行尚未执行的新的路径,则符号执行引擎只能使用已求得的新用例再迭代进行concolic执行,以下结合第三代码进行详细说明:
由上述第三代码所示可知,通过int foo定义了为返回整形值函数,通过char定义了字符类型,其中,p为指向整形变量的指针变量,通过int r定义r为整形变量,且r的循环初值为0;循环语句for(int i=0;i<6;i++)具体指,int i=0循环变量所赋的初值为0,循环条件为i<6,循环变量增值为i++;
通过上述所示的第三代码所示可知,char*secret=“secret”指示指针p所指向的字符串为“secret”,if(p[i]==secret[i])指示,指针p所指示的字符串的第i个字符与secret的第i个字符是否相同;在r取值取到6时,函数将触发bug()函数,否则正常返回0。但是使用concolic的方式产生一个使foo能触发bug()的输入并不容易。
以下结合具体示例进行说明:假设在concolic执行时,第一次测试所使用的初始输入p=“aaaaa”。
初始时,路径约束集合为空{},p指向的内存作为符号值时其内容可以为任意值,本次符号执行引擎纪录着它本次实际参考值“aaaaa”。
第一次循环i=0,所以判断条件为:if(p[i]==secret[i])为if(p[0]==secret[0]),根据初始输入p=“aaaaa”可知,p[0]=‘a’,而secret[i]=secret[0])=‘s’,可知,p[0]与secret[0]不相同,则可知本次实际值比较结果是false,符号执行引擎可知本次循环的程序分支为false的路径,即输入值指引的路径未进入r++的操作。此时符号执行引擎将进行如下所示的两项工作,此时将启用p指向的内存的符号特性:
1、因本次实际值比较结果是false,则将false==(p[0]==‘s’)加入if(p[i]==secret[i])处的路径约束集合中,准备继续向下按实际输入值(p=“aaaaa”)指引的路径执行;
2、将false==(p[0]==‘s’)求反并在if(p[i]==secret[i])处的路径约束集合下求解,因为当前路径约束集合为空,所以待求解集合为{True==(p[0]==‘s’)},以得到新用例,该新的用例为使得if(p[0]==secret[0])的实际值比较结果为True的用例,比如p=“xaaaa”。
实施例对所求取的新的用例p不做限定,只要所求取出的新的用例中的第一个字符不是字符a即可;
在第二次循环时,在if(p[i]==secret[i])处的路径约束集合为{false==(p[0]==‘s’)}。此时i=1,根据输入p=“aaaaa”可知,p[1]=‘a’,而secret[i]=secret[1])=‘e’,可知,p[1]与secret[1]不相同,则本次循环的程序分支为false的路径,即输入值指引的路径未进入r++的操作。此时符号执行引擎将进行如下所示的两项工作,此时将启用p指向的内存的符号特性:
1、因本次实际值比较结果是false,则将false==(p[1]==‘e’)加入if(p[i]==secret[i])处的路径约束集合,同时准备继续向下按实际输入值(p=“aaaaa”)指引的路径执行;
2、求解可以进入未进分支的用例,方法如下,将false==(p[1]==‘e’)求反,得到方程C:True==(p[1]==‘e’),在if(p[i]==secret[i])处已有的路径约束集合下求解该方程,if(p[i]==secret[i])处已有的路径约束集合内容为PathC={false==(p[0]==‘s’)},在该路径约束集合内容下求解方程C的用例,即求解同时满足PathC和C的用例,该新用例使得程序可以运行至if(p[1]==secret[1])处,且比较结果为True。举例,求解器可能返回的新用例为p=“xsaaa”。
类似地接下来执行i=3,i=4,i=6……,具体在本实施例中不做赘述。
依次类推,可进行第二次测试、第三次测试等,直至触发bug()。
可见,原始的concolic执行其实是对路径空间的穷举,在第三代码中,如果要得到触发bug()输入,最差情况下要求解2n次方,n为所定义的字符所包括的字符数量,本实施例中,通过函数char所定义的字符“secret”所包括的字符数量为6,则本实施例所示的符号执行引擎最差需要执行26=32次才能实现触发bug(),即尝试次数是与路径空间大小相等的,随着循环次数增加,效率呈指数下降。
原始concolic执行的提出就是为了缓解符号执行的路径爆炸,然而上述所示的原始concolic执行的方案的低效其实会导致在很多场景下原始concolic执行的资源消耗和符号执行是一样的。
因原始的concolic执行的方案,在一次循环中只能够执行确定值所指引的一条路径,无法对应用程序的整体逻辑有完整了解,即只跟踪一条特定路径,这是导致原始的concolic执行的方案求解在很多场景下不能够有效的缓解路径爆炸的根本。而且原始的concolic执行的方案因一次循环中只能够执行确定值所指引的一条路径,在程序分支处只能够执行一条路径,导致符号执行引擎所收集到的路径所运行的逻辑和应用程序完整的运行逻辑存在偏差,致使路径约束求解时可能失败。
为了提升concolic的效率,以下提出了一种基于路径合并和复制的concolic执行方法,该方法本质上是不完全使用concolic执行,而是在关键程序分支点启用上述所示的符号执行,以更好地收集应用程序逻辑。
以下结合图3所示对基于路径合并和复制的concolic执行方法的具体执行过程进行示例性说明:其中,图3所示为所述第三代码的执行流程图;
如图3所示可知,if(p[0]==‘s’)的True和false分支的操作最终都到达if(p[1]==‘e’)处。对该代码片段的路径合并方法的使用步骤如下(如图4所示):
在if(p[0]==‘s’)处,符号执行引擎进行如下所示的两项工作:
1、继续以p=“aaaaa”为例,则可知在第一次循环中,在if(p[i]==secret[i])处的实际值比较结果是false,求反产生使比较结果为True的新输入用例,这与上述所示的原始concolic方式相同,具体不做赘述;
2、路径复制,即对分支判断的两个分支都进行执行。两条路径分别拥有路径约束{T==(p[0]==‘s’)}和{F=={p[0]==‘s’},以P1代表True的程序分支,以P2代表false的程序分支。
在到达if(p[1]==‘e’)处时,P1,P2符合可以合并的条件,具体的,两条路径能够进行合并的条件是指,两条路径源自同一条件判断点,且两条路径能够汇合到同一点,即两条路径能够汇聚到共同的终点;
因路径P1以及路径P2均源自同一条件判断点,即if(p[0]==‘s’)处,且路径P1以及路径P2能够汇合到同一点if(p[1]==‘e’)处,所以本实施例所示的符号执行引擎可将路径P1以及路径P2进行合并。
在P1中,r=1,在P2中,r=0,故合并后r的值为r=ite(p[0]==’s’,1,0)。同时合并后的路径的约束为空。其中,条件选择算符(if-then-else,ite)算符,具体的,r=ite(p[0]==‘s’,1,0)的含义是指,p[0]==‘s’的比较值为真时,r=1,p[0]==‘s’的比较值为假时,r=0;
同样的方式,在执行完if(p[1]==‘e’)后到达if(p[2]==‘c’)时,r的值变为r=ite(p[1]==‘e’,ite(p[0]==‘s’,1,0)+1,ite(p[0]==‘s’,1,0))。具体的,r=ite(p[1]==‘e’,ite(p[0]==‘s’,1,0)+1,ite(p[0]==‘s’,1,0))的含义是指,ite(p[1]==‘e’的实际比较值为真时,r=ite(p[0]==‘s’,1,0)+1,ite(p[1]==‘e’的实际比较值为假时,r=ite(p[0]==‘s’,1,0);
类似地继续执行后续应用程序的判断分支,具体执行过程,如上述所示,具体不做赘述;
到达if(r==6)判断点处,在原始concolic方式中,该判断点的真假与符号值无关,所以无法求反得到新用例。但通过路径复制与合并的方法,r的值已经变为与符号值有关,该判断点变为与符号值有关,若实际值所指引的结果是false==(r==6),则将其求反,即可得到True==(r==6),继而一次成功得到输入值:“secret”。
可以看到,路径复制再合并实际上是将两条路径的信息,即各路径的路径约束都集中到一个路径中,使concolic在一条基础路径上向广度上进行了适当延伸。理论上符号执行引擎可以通过在concolic的指引路径基础上复制合并大幅提升concolic的输出用例的能力,结合原始concolic的执行方式和基于路径合并和复制的concolic的执行方式可知,同样测试第三代码,采用原始concolic的执行方式最差的情况需要32次才能够正确的输出字符“secret”,而采用基于路径合并和复制的concolic的执行方式可知,可一次输出字符“secret”。
但是,基于路径合并和复制的concolic的执行方式,路径复制再合并方法的资源开销较大,路径复制需要一些状态量复制,路径合并时需要对两条路径各自运行时所需要的内存变量值进行逐一比对,以判断两条路径是否符合上述所示的能够进行路径合并的条件,这都是耗时的操作。当内存变量空间很大时,很明显路径的合并将变得很耗时,而且两条路径的路径约束集合内,不同的路径约束可能非常的少,但是却需要对每条路径的路径约束集合分别完整的进行获取,从而造成了内存的浪费。
以下结合图5所示对本实施例所提供的能够避免路径爆炸而且能够遍历代码所包括的所有路径的符号执行方法的具体执行过程进行说明:
步骤501、符号执行引擎识别被测试代码所包括的代码基本块。
本实施例中,所述符号执行引擎对被测试代码进行识别,以识别出被测试代码所包括的各代码基本块,代码基本块的预设代码执行顺序的说明可参见图6所示为例,本实施例所示的所述代码基本块包括父节点、第一子节点、第二子节点以及结束节点,所述代码基本块的预设代码执行顺序包括第一执行路径以及第二执行路径,所述第一执行路径按代码执行顺序依次降低的排序依次包括所述父节点、所述第一子节点和所述结束节点,所述第二执行路径按代码执行顺序依次降低的排序依次包括所述父节点、所述第二子节点和所述结束节点,且所述第一子节点和所述第二子节点之间无代码执行的先后顺序。
具体的,本实施例所示的符号执行引擎对被测试代码进行遍历分析以获取出所述被识别代码所包括的各个代码基本块,所述代码基本块是指存储位置连续且必定执行连续的代码片段,导致不连续的操作包括但不限于函数调用,分支等等,只要使代码的执行流在内存上或逻辑上不连续的指令皆可。
为更好的理解本实施例所示的所述代码基本块的结构,以下结合下述所示的第四代码和图7所示对代码基本块的结构进行说明:
上述第四代码指示,通过int foo定义了为返回整形值函数,通过int x定义了输入参数x为整形变量,通过int x定义了初始的输入参数r为0以及t;通过代码if(x==0x123456)定义了判断条件为if(x==0x123456),若真,则执行代码r=1,即在判断条件if(x==0x123456)为真时,确定r=1;在判断条件if(x==0x123456)为假时,确定r=0,并确定t=r,并如第四代码return t所示,在符号执行引擎确定出t的具体取值后,所述符号执行引擎通过foo函数将t带回调用处。
参见图7所示,本实施例所示的符号执行引擎对第四代码进行分析后可知,代码“int r=0,t;if(x==0x123456)”作为程序的分支节点,可成为代码基本块的父节点,与父节点连接的两个子节点为与所述父节点连接的两个程序分支,以上述第四代码所示可知,与所述父节点“if(x==0x123456)”连接的第一子节点可为if(x==0x123456)为真时所进入的程序分支,即所述第一子节点为“r=1”,与所述父节点“if(x==0x123456)”连接的第二子节点可为if(x==0x123456)为假时所进入的程序分支,即所述第二子节点为“r=0”。
所述第一子节点和所述第二子节点同时汇聚的节点为结束节点,即所述结束节点同时与所述第一子节点和所述第二子节点连接,在第四代码中,所述结束节点为“t=r”。
本实施例中,所述第一子节点和所述第二子节点中,可能有1个位空,也可能有0个为空,只要所述第一子节点和所述第二子节点不同时为空即可,如上述所示的第三代码以及图8所示可知,所述符号执行引擎对第三代码进行分析可确定出多个代码基本块,其中第三代码在第一次循环i=0的情况下,所述父节点为“if(p[0]==‘s’。
在“if(p[0]==‘s’为真时所进入的子节点为r++,在“if(p[0]==‘s’为假时所进入的子节点为空,且该代码基本块的结束节点为“if(p[1]==‘e’。
本实施例对本测试代码所包括的代码基本块的具体数量不做限定,且本实施例对多个代码块之间的连接关系也不做限定,例如,以图9所示为例,被测试代码所包括的多个代码基本块可为依次连接的结构,以图9所示的示例中,被测试代码可包括有两个代码基本块,且两个代码基本块呈串联的结构,第一个代码基本块的结束节点可作为第二个代码基本块的父节点,又如,本实施例所示的代码基本块可以嵌套形成更为复杂的结构,以图10所示为例,被测试代码可包括有两个代码基本块,即第一代码基本块和第二代码基本块,而第一代码基本块具体包括父节点1001、第一子节点1002、第二子节点1003以及结束节点1004,而整个所述第一代码基本块可作为第二代码基本块的第二子节点1005,可见,外层的第二代码基本块包括父节点1006、第一子节点1007、第二子节点1005以及结束节点1008。
步骤502、符号执行引擎执行父节点。
本实施例所示的符号执行引擎在识别出代码基本块时,可首先基于已识别出的代码基本块确定执行树,所述执行树用于对代码基本块的预设代码执行顺序进行更改,所述符号执行引擎所确定出的所述确定执行树包括所述父节点、所述第一子节点、所述第二子节点以及所述结束节点,所述执行树所包括的所述父节点、所述第一子节点、所述第二子节点以及所述结束节点的代码执行顺序依次降低。可见,所述执行树中,所述父节点具有最高的执行顺序优先级,所述结束节点具有最低的执行顺序优先级。
以图11所示为例,所述符号执行引擎对所述代码基本块所创建的执行树可如图11所示,即所述执行树所包括的所述父节点、所述第一子节点、所述第二子节点以及所述结束节点的执行优先级依次递减。本实施例对所述第一子节点和所述第二子节点在所述执行树中的位置为可选的说明,不做限定,只要所述第一子节点和所述第二子节点在所述父节点和所述结束节点之间即可,例如,所述执行树还可包括所述父节点、所述第二子节点、所述第一子节点以及所述结束节点。
本实施例对所述符号执行引擎创建执行树的说明为可选的示例,不做限定,只要所述符号执行引擎能够确定出执行所述父节点、所述第一子节点、所述第二子节点以及所述结束节点的执行优先级依次递减即可。
所述符号执行引擎根据所述父节点确定出所述父节点所定义的初始定义数据,其中,所述初始定义数据为输入至所述代码基本块的数据,以第一代码为例,所述符号执行引擎可确定出输入至所述代码基本块的初始定义数据为输入参数x,以第二代码为例,所述符号执行引擎可确定出输入至代码基本块的初始定义数据为int i=0。
所述符号执行引擎执行所述父节点,在执行至父节点结尾处时,不进行上述所示的路径复制,而是将父节点结尾处的约束条件进行记录,供后续符号执行过程使用。
具体的,所述第一约束条件为执行所述第一子节点的条件,所述第二约束条件为执行所述第二子节点的条件,以上述所示的第一代码为例,在父节点为“if(x>10)”时,则执行至所述父节点的结尾处,可确定该父节点的第一约束条件为True==(x>10),而该父节点的第二约束条件为false==(x>10),又以上述所示的第四代码所示为例,在父节点为“if(x==0x123456)”时,则执行至所述父节点的结尾处,可确定该父节点的第一约束条件为True==(x==0x123456),而该父节点的第二约束条件为false==(x==0x123456)。
步骤503、符号执行引擎执行第一子节点。
具体的,根据所述符合执行引擎已创建的所述执行树可知,在所述符号执行引擎执行完所述父节点后,直接执行所述第一子节点,而且在本实施例中,所述符号执行引擎在执行完所述父节点后,不创建父节点对应的路径约束集合,只是将所述第一约束条件和所述第二约束条件存储在内存中。
在所述符号执行引擎执行所述第一子节点的具体过程中,所述符号执行引擎根据所述第一子节点对所述初始定义数据进行携带所述第一约束条件的赋值操作,以生成第一存储数据集合。
具体的,本实施例所示的携带第一约束条件的赋值操作是指:
现有的符号执行中,对一个变量X赋值为v的操作很直接,就是X等于v,即X=v。如果v是常量,则被赋值的X也会变为常量。本实施例所示的携带第一约束条件的赋值操作,是指在赋值操作时,逻辑上满足第一约束条件后才进行新值覆盖,否则保持旧值。具体做法是,设第一约束条件为e,变量X的初始值为x0,变量X在e满足时赋值为v,变量X在e不满足时保持旧值x0,则对X进行携带约束的赋值操作后X的值为X=ite{e,v,x0},这种数值的表示方法为条件选择算符。
可见,本实施例在符号执行引擎执行所述第一子节点时,可根据所述第一子节点对所述初始定义数据进行携带所述第一约束条件的赋值操作,以生成第一存储数据集合,其中,所述第一存储数据集合包括所述第一约束条件、所述第一子节点所定义的数据以及所述初始定义数据,通过条件选择算符对所述第一存储数据集合进行表示,则第一存储数据集合=ite{第一约束条件,第一子节点所定义的数据,初始定义数据},则此时所述第一存储数据集合用于指示,在所述初始定义数据满足所述第一约束条件时,根据所述第一子节点所定义的数据对所述初始定义数据进行赋值,在所述初始定义数据不满足所述第一约束条件时,则所述初始定义数据保持不变。
为更好的理解执行所述第一子节点的具体过程,以下结合第四代码所示对执行所述第一子节点的具体过程进行示例性说明:
经过上述所示可知,本实施例所示的所述第一子节点为“r=1”,其中,r=1为所述第一子节点所定义的数据。可见,本实施例所示的所述第一子节点用于定义在初始定义数据“int r=0”满足所述第一约束条件“True==(x==0x123456)”时,则通过所述第一子节点所定义的数据(r=1),对所述初始定义数据“int r=0”进行新值覆盖。
在符号执行引擎执行上述所示的第四代码的第一子节点后,所述符号执行引擎即可获取所述第一存储数据集合为r=ite(True==(x==0x123456),1,0),即在执行如第四代码所示的第一子节点时,所述符号执行引擎不会根据父节点“if(x==0x123456)”的判断结果判断执行哪一个子节点,而是根据预先配置的执行树直接执行所述第一子节点,并根据第一子节点的执行结果配置所述第一存储数据集合。
在所述符号执行引擎获取到所述第一存储数据集合后,所述符号执行引擎不会如现有技术所示针对所述第一子节点创建路径约束集合,而是仅将所获取到的所述第一存储集合写入至内存,即以第四代码所示为例,所述符号执行引擎将r=ite(True==(x==0x123456),1,0)写入至内存,以使所述内存的存储状态值为r=ite(True==(x==0x123456),1,0)。
步骤504、符号执行引擎执行第二子节点。
具体的,根据所述符合执行引擎已创建的所述执行树可知,在所述符号执行引擎执行完所述第一子节点后,直接执行所述第二子节点,在所述符号执行引擎执行所述第二子节点的具体过程中,所述符号执行引擎根据所述第二子节点对所述初始定义数据进行携带所述第二约束条件的赋值操作,以生成第二存储数据集合。
具体的,本实施例所示的携带第二约束条件的赋值操作的具体说明,可详见步骤504所示的携带第一约束条件的赋值操作的具体说明,具体在本实施例中不做赘述。
需明确的是,执行本实施例所示的步骤505时的内存的存储状态值为所述第一存储数据集合,在此基础上,所述符号执行引擎继续执行本实施例所示的步骤505以进行第二子节点的执行以生成第二存储数据集合,其中,所述第二存储数据集合包括所述第二约束条件、所述第二子节点所定义的数据以及所述第一存储数据集合,并通过条件选择算符对所述第二存储数据集合进行表示,则第二存储数据集合=ite{第二约束条件,第二子节点所定义的数据,第一存储数据集合},则此时所述第二存储数据集合用于指示,在所述初始定义数据满足所述第二约束条件时,根据所述第二子节点所定义的数据对所述初始定义数据进行赋值,在所述初始定义数据不满足所述第二约束条件时,则根据所述第一存储数据集合对所述初始定义数据进行赋值。
为更好的理解执行所述第二子节点的具体过程,以下结合第四代码所示对执行所述第二子节点的具体过程进行示例性说明:
经过上述所示可知,本实施例所示的所述第二子节点为“r=0”,其中,r=0为所述第二子节点所定义的数据。可见,本实施例所示的所述第二子节点用于定义,在初始定义数据“int r=0”满足所述第二约束条件“False==(x==0x123456)”时,通过所述第二子节点所定义的数据(r=0),对所述初始定义数据“int r=0”进行新值覆盖,即r=ite(True==(x==0x123456),1,0)。
在符号执行引擎执行上述所示的第四代码的第二子节点后,所述符号执行引擎即可获取所述第二存储数据集合为r=ite(False==(x==0x123456),0,ite(True==(x==0x123456),1,0)。
在所述符号执行引擎获取到所述第二存储数据集合后,所述符号执行引擎不会如现有技术所示针对所述第二子节点创建路径约束集合,而是仅将所获取到的所述第二存储集合写入至内存,即以第四代码所示为例,所述符号执行引擎将r=ite(False==(x==0x123456),0,ite(True==(x==0x123456),1,0)写入至内存,以使所述内存的存储状态值为r=ite(False==(x==0x123456),0,ite(True==(x==0x123456),1,0)。
本实施例中,因执行树的设置,则所述符号执行引擎先执行步骤504以对第一子节点进行执行,后执行步骤505以对第二子节点进行执行,若在其他示例中,即在执行树中,所述第二子节点的执行优先级高于所述第一子节点的执行优先级,则所述符号执行引擎可首先执行第二子节点,后执行所述第一子节点,即本实施例对执行所述第一子节点和执行所述第二子节点的具体顺序不做限定。
步骤505、符号执行引擎执行所述结束节点。
具体的,所述符号执行引擎可根据所述结束节点所包括的具体代码确定执行所述结束节点的具体方式,以第四代码所示可知,在所述结束节点为“return t”所示可知,则所述符号执行引擎可通过foo函数将参数t带回调用处。
若所述执行树的结构为如图10所示的代码基本块的嵌套结构,则只需要递归执行上述步骤即可。
采用本实施例所示的符号执行的方法所示可知,在符号执行过程中,无论初始定义数据具体的取值为何,所述符号执行引擎均可遍历所述代码基本块所包括的任一路径,而且在遍历所述代码基本块所包括的任一路径的过程中,无需对代码基本块所包括的路径进行复制以及合并的操作,只要在执行第一子节点时,符号执行引擎根据所述第一子节点对所述初始定义数据进行携带所述第一约束条件的赋值操作即可,在执行第二子节点时,符号执行引擎根据所述第二子节点对所述初始定义数据进行携带所述第二约束条件的赋值操作即可,通过本实施例所示的携带第一约束条件以及携带第二约束条件的赋值操作,在无需对路径进行合并以及复制的操作,即可一次完成对所述代码基本块所包括的所有路径的遍历,提高了对被测试代码所包括的路径进行遍历的效率。
具体的,由上述所示对所述代码基本块的结构的说明可知,被测试代码中所具有的代码基本块是使得对被测试代码进行符号执行效率变低的重要原因,因为一个代码基本块的出现,若采用原始的concolic执行方式,在一次执行过程中,会缺少对第一子节点或第二子节点的一次信息收集,因对第一子节点或第二子节点的缺少一次信息收集,这样如果后续的分支判断点与缺失的子节点信息相关的话,那么求解可能会失败,原始的concolic执行方式的具体说明,请详见上述所示,具体不做赘述。如果被测试代码包括有N个串联的代码基本块,则该被测试代码的逻辑上路径空间数为2N,一次原始的concolic执行方式仅收集其中1/2N的信息量,而采用本实施例所示的方法,因通过上述所示的携带约束条件的赋值操作,无需对父节点、第一子节点以及第二子节点进行路径约束集合的创建,则本实施例所示的符号执行一次的执行过程,即可收集被测试代码全部的2N个信息量,相对于原始的concolic执行方式有效的提高了路径遍历的效率。
现有技术还提供了一种基于路径合并和复制的concolic的执行方式,在此种方式中所提到的路径复制再合并的方法本质上就是缓解代码基本块的影响。执行代码基本块的父节点时,符号执行引擎进行路径复制的操作,而在执行到父节点的结尾处,两条复制出来的路径又合并成一条路径,同时将两条路径的影响通过ite表达式表达出来,此种方式对被测试代码执行框架上改动较大,且求反的方式本质上是一种穷举用例的方式,非常的耗时耗资源,效率低下,实际不实用,而采用本实施例所示的方法,在对代码基本块运行之前,和对代码基本块运行之后,除内存的存储状态值有所变化外,其他状态没有发生改变,即执行本实施例所示的符号执行方法,唯一改变的是内存的存储状态值,在无需进行路径符合与合并的操作的情况下,即可实现对代码基本块所包括的所有路径的逻辑信息的完整收集,有效的省去了路径复制与合并时的额外开销,效率得到提升。
通过和现有技术所示的符号执行方案的比对说明可知,本实施例所示的符号执行方法无需被测试代码的路径的复制与合并操作,本实施例所示的方法只需要只跟踪一条程序路径,在遇到条件分支时不进行态复制,只需要进行携带约束条件的赋值操作即可,可见,本实施例所示的方法在不改变被测试代码的机制的基础上实现,有效的提高了路径遍历的效率。而且通过携带约束条件的赋值操作,可将程序的分支条件写入到内存中,使约束条件在数据集合中传递,降低了路径遍历的耗时,节省了内存资源。
为更好的理解本实施例所示的符号执行方法,以下结合第五代码所示的应用场景进行具体的说明:
上述所示的第五代码具体是指,通过void bin2ascii定义没有返回值的空类型自定义函数名为bin2ascii;通过unsigned char*p定义字符类型p为无符号整数变量;通过int len定义自定义的函数名为len;通过int i,j定义输入参数i以及j为整形变量;循环语句for(j<2;j++)具体是指,j循环变量的循环条件为j<2,循环变量增值为j++;unsignedchar x=p[i]是指,将p[i]赋值给参数x;unsigned char ch=(x>>4*(1-j)&0xf)是指,定义字符类型ch的初值为“(x>>4*(1-j)&0xf)”应用程序分支if(ch<=9),在约束if为True的应用程序分支,即True==(ch<=9)时,输出值为“out[i*2+j]=ch+'0'”;在约束if为False的应用程序分支,即False==(ch<=9)时,输出值为“out[i*2+j]=(ch-0xA)+'A'”;
通过int test_func(char*p)定义了函数test_func的参数为char*p,char*target="3E2B1C4D335F3C3A3E3BA3E3"定义了函数char*target的取值;char buff[256*2]={0}定义了buff这样的数组大小为256*2=0;bin2ascii(p,buff,strlen(target))定义了自定义函数bin2ascii所包括的参数为p,buff,strlen(target);if((strcmp((char*)buff,target)==0))定义了若strcmp((char*)buff,target)==0,则触发bug()。
所述符号执行执行对上述所示的第五代码进行分析即可确定上述第五代码为代码基本块,所述符号执行引擎根据所述第五代码可确定出父节点为“unsigned char ch=(x>>4*(1-j)&0xf),if(ch<=9)”,第一子节点为“out[i*2+j]=ch+'0'”,第二子节点为“out[i*2+j]=(ch-0xA)+'A'”,结束节点为“j++”。
所述符号执行引擎根据上述已确定的所述代码基本块所配置的执行树可参见图12所示,则所述符号执行引擎获取所述代码基本块对应的初始定义数据,如上述第五代码所示客户自,初始定义数据为“unsigned char ch=(x>>4*(1-j)&0xf)”;
所述符号执行引擎根据如图12所示的执行树,先执行所述父节点,并记录第一约束条件以及第二约束条件,其中,所述第一约束条件为True==(ch<=9),所述第二约束条件为False==(ch<=9);
所述符号执行引擎执行第一子节点“out[i*2+j]=ch+'0'”,并生成第一存储数据集合out[i*2+j]=ite(True==(ch<=9),ch+'0',0),对所述第一存储数据集合生成的具体过程的说明,请参见图5所示的实施例,具体在本应用场景中不做赘述;
所述符号执行引擎执行第二子节点“out[i*2+j]=(ch-0xA)+'A'”,并生成第二存储数据集合out[i*2+j]=ite(False==(ch<=9),(ch-0xA)+'A',ite(True==(ch<=9),ch+'0',0)),对所述第二存储数据集合生成的具体过程的说明,请参见图5所示的实施例,具体在本应用场景中不做赘述;
通过上述所示的第五代码所示可知,为对上述所示的第五代码所包括的任一路径进行遍历,则需要触发bug()执行,而因所述第五代码中所述代码基本块的存在,则需要不断的循环才能使得测试过程触发bug(),可见,通过现有技术所示的符号执行方法触发bug()的概率极小;具体因target的长度为24个字节,所以原始的concolic的执行方法最多要进行224次尝试方能得到触发bug()的输入,这是极其浪费时间和内存资源的,而采用本实施例所示的符号执行的方法,在进行strcmp时,由于bintoascii的应用程序逻辑收集完全,所以可以很容易求得触发bug()的新输入,又因将第一约束条件和第二约束条件写入至内存中而不是约束条件集合中,大大降低了开销,且经过实际对上述所示的第五代码的测试,采用现有技术所示的方案,能够触发发bug()的输入的概率很低,几乎是无解的,而采用本实施例所示的方法,在小于0.3秒的执行时间即可成功触发bug(),有效的提高了对被测试代码所包括的路径进行遍历的效率。
以下结合图13所示对本实施例所示的电子设备的具体结构进行示例性说明,图13所示的电子设备用于执行上述符号执行引擎所具有的功能,以使本实施例所示的电子设备能够执行上述实施例所示的符号执行方法,所述符号执行方法的具体执行过程,请详见上述实施例所示,具体在本实施例中不做赘述。
如图13所示,所述电子设备具体包括:
确定单元1301,用于确定代码基本块,所述代码基本块包括父节点、第一子节点、第二子节点以及结束节点,所述代码基本块的预设代码执行顺序包括第一执行路径以及第二执行路径,所述第一执行路径按代码执行顺序依次降低的排序依次包括所述父节点、所述第一子节点和所述结束节点,所述第二执行路径按代码执行顺序依次降低的排序依次包括所述父节点、所述第二子节点和所述结束节点,且所述第一子节点和所述第二子节点之间无代码执行的先后顺序;
可选的,所述确定单元1301还用于,确定执行树,所述执行树包括所述父节点、所述第一子节点、所述第二子节点以及所述结束节点,所述执行树所包括的所述父节点、所述第一子节点、所述第二子节点以及所述结束节点的代码执行顺序依次降低。
第一执行单元1302,用于根据所述父节点确定初始定义数据、第一约束条件以及第二约束条件,所述第一约束条件为执行所述第一子节点的条件,所述第二约束条件为执行所述第二子节点的条件;
第二执行单元1303,用于根据所述第一子节点对所述初始定义数据进行携带所述第一约束条件的赋值操作以生成第一存储数据集合,所述第一存储数据集合包括所述第一约束条件、所述第一子节点所定义的数据以及所述初始定义数据;
具体的,所述第二执行单元1303包括:
第一获取模块13031,用于获取所述第一子节点所定义的数据;
第一生成模块13032,用于生成所述第一存储数据集合,所述第一存储数据集合用于指示,在所述初始定义数据满足所述第一约束条件时,根据所述第一子节点所定义的数据对所述初始定义数据进行赋值,在所述初始定义数据不满足所述第一约束条件时,所述初始定义数据保持不变。
更具体的,所述第二执行单元1303还用于,将所述第一存储数据集合写入至内存,以使所述内存的存储状态值为所述第一存储数据集合。
第三执行单元1304,用于根据所述第二子节点对所述初始定义数据进行携带所述第二约束条件的赋值操作以生成第二存储数据集合,所述第二存储数据集合包括所述第二约束条件、所述第二子节点所定义的数据以及所述第一存储数据集合;
具体的,所述第三执行单元1304包括:
第二获取模块13041,用于获取所述第二子节点所定义的数据;
第二生成模块13042,用于生成所述第二存储数据集合,所述第二存储数据集合用于指示,在所述初始定义数据满足所述第二约束条件时,根据所述第二子节点所定义的数据对所述初始定义数据进行赋值,在所述初始定义数据不满足所述第二约束条件时,根据所述第一存储数据集合对所述初始定义数据进行赋值。
更具体的,所述第三执行单元1304还用于,将所述第二存储数据集合写入至所述内存,以使所述内存的存储状态值为所述第二存储数据集合。
本实施例所示的电子设备执行上述实施例所示的符号执行方法的有益效果的说明,请详见图5所示的实施例,具体在本实施例中不做赘述。
所属领域的技术人员可以清楚地了解到,为描述的方便和简洁,上述描述的系统,装置和单元的具体工作过程,可以参考前述方法实施例中的对应过程,在此不再赘述。
在本申请所提供的几个实施例中,应该理解到,所揭露的系统,装置和方法,可以通过其它的方式实现。例如,以上所描述的装置实施例仅仅是示意性的,例如,所述单元的划分,仅仅为一种逻辑功能划分,实际实现时可以有另外的划分方式,例如多个单元或组件可以结合或者可以集成到另一个系统,或一些特征可以忽略,或不执行。另一点,所显示或讨论的相互之间的耦合或直接耦合或通信连接可以是通过一些接口,装置或单元的间接耦合或通信连接,可以是电性,机械或其它的形式。
所述作为分离部件说明的单元可以是或者也可以不是物理上分开的,作为单元显示的部件可以是或者也可以不是物理单元,即可以位于一个地方,或者也可以分布到多个网络单元上。可以根据实际的需要选择其中的部分或者全部单元来实现本实施例方案的目的。
另外,在本发明各个实施例中的各功能单元可以集成在一个处理单元中,也可以是各个单元单独物理存在,也可以两个或两个以上单元集成在一个单元中。上述集成的单元既可以采用硬件的形式实现,也可以采用软件功能单元的形式实现。
所述集成的单元如果以软件功能单元的形式实现并作为独立的产品销售或使用时,可以存储在一个计算机可读取存储介质中。基于这样的理解,本发明的技术方案本质上或者说对现有技术做出贡献的部分或者该技术方案的全部或部分可以以软件产品的形式体现出来,该计算机软件产品存储在一个存储介质中,包括若干指令用以使得一台计算机设备(可以是个人计算机,服务器,或者网络设备等)执行本发明各个实施例所述方法的全部或部分步骤。而前述的存储介质包括:U盘、移动硬盘、只读存储器(ROM,Read-OnlyMemory)、随机存取存储器(RAM,Random Access Memory)、磁碟或者光盘等各种可以存储应用程序代码的介质。
以上所述,以上实施例仅用以说明本发明的技术方案,而非对其限制;尽管参照前述实施例对本发明进行了详细的说明,本领域的普通技术人员应当理解:其依然可以对前述各实施例所记载的技术方案进行修改,或者对其中部分技术特征进行等同替换;而这些修改或者替换,并不使相应技术方案的本质脱离本发明各实施例技术方案的精神和范围。
Claims (19)
1.一种符号执行方法,其特征在于,包括:
确定代码基本块,所述代码基本块包括父节点、第一子节点、第二子节点以及结束节点,所述代码基本块的预设代码执行顺序包括第一执行路径以及第二执行路径,所述第一执行路径按代码执行顺序依次降低的排序依次包括所述父节点、所述第一子节点和所述结束节点,所述第二执行路径按代码执行顺序依次降低的排序依次包括所述父节点、所述第二子节点和所述结束节点,且所述第一子节点和所述第二子节点之间无代码执行的先后顺序;
根据所述父节点确定初始定义数据、第一约束条件以及第二约束条件,所述第一约束条件为执行所述第一子节点的条件,所述第二约束条件为执行所述第二子节点的条件;
根据所述第一子节点对所述初始定义数据进行携带所述第一约束条件的赋值操作以生成第一存储数据集合,所述第一存储数据集合包括所述第一约束条件、所述第一子节点所定义的数据以及所述初始定义数据;
根据所述第二子节点对所述初始定义数据进行携带所述第二约束条件的赋值操作以生成第二存储数据集合,所述第二存储数据集合包括所述第二约束条件、所述第二子节点所定义的数据以及所述第一存储数据集合。
2.根据权利要求1所述的方法,其特征在于,所述根据所述第一子节点对所述初始定义数据进行携带所述第一约束条件的赋值操作以生成第一存储数据集合包括:
获取所述第一子节点所定义的数据;
生成所述第一存储数据集合,所述第一存储数据集合用于指示,在所述初始定义数据满足所述第一约束条件时,根据所述第一子节点所定义的数据对所述初始定义数据进行赋值,在所述初始定义数据不满足所述第一约束条件时,所述初始定义数据保持不变。
3.根据权利要求1或2所述的方法,其特征在于,所述根据所述第二子节点对所述初始定义数据进行携带所述第二约束条件的赋值操作以生成第二存储数据集合包括:
获取所述第二子节点所定义的数据;
生成所述第二存储数据集合,所述第二存储数据集合用于指示,在所述初始定义数据满足所述第二约束条件时,根据所述第二子节点所定义的数据对所述初始定义数据进行赋值,在所述初始定义数据不满足所述第二约束条件时,根据所述第一存储数据集合对所述初始定义数据进行赋值。
4.根据权利要求1至3任一项所述的方法,其特征在于,所述确定代码基本块之后,所述方法还包括:
确定执行树,所述执行树包括所述父节点、所述第一子节点、所述第二子节点以及所述结束节点,所述执行树所包括的所述父节点、所述第一子节点、所述第二子节点以及所述结束节点的代码执行顺序依次降低。
5.根据权利要求1至4任一项所述的方法,其特征在于,所述根据所述第一子节点对所述初始定义数据进行携带所述第一约束条件的赋值操作以生成第一存储数据集合之后,所述方法还包括:
将所述第一存储数据集合写入至内存,以使所述内存的存储状态值为所述第一存储数据集合。
6.根据权利要求5所述的方法,其特征在于,所述根据所述第二子节点对所述初始定义数据进行携带所述第二约束条件的赋值操作以生成第二存储数据集合之后,所述方法还包括:
将所述第二存储数据集合写入至所述内存,以使所述内存的存储状态值为所述第二存储数据集合。
7.根据权利要求6所述的方法,其特征在于,所述第一存储数据集合以条件选择算符的方式存储于所述内存中,所述第二存储数据集合以条件选择算符的方式存储于所述内存中。
8.根据权利要求1至7任一项所述的方法,其特征在于,所述第一子节点以及所述第二子节点中,有1个或0个为空。
9.一种电子设备,其特征在于,包括:
确定单元,用于确定代码基本块,所述代码基本块包括父节点、第一子节点、第二子节点以及结束节点,所述代码基本块的预设代码执行顺序包括第一执行路径以及第二执行路径,所述第一执行路径按代码执行顺序依次降低的排序依次包括所述父节点、所述第一子节点和所述结束节点,所述第二执行路径按代码执行顺序依次降低的排序依次包括所述父节点、所述第二子节点和所述结束节点,且所述第一子节点和所述第二子节点之间无代码执行的先后顺序;
第一执行单元,用于根据所述父节点确定初始定义数据、第一约束条件以及第二约束条件,所述第一约束条件为执行所述第一子节点的条件,所述第二约束条件为执行所述第二子节点的条件;
第二执行单元,用于根据所述第一子节点对所述初始定义数据进行携带所述第一约束条件的赋值操作以生成第一存储数据集合,所述第一存储数据集合包括所述第一约束条件、所述第一子节点所定义的数据以及所述初始定义数据;
第三执行单元,用于根据所述第二子节点对所述初始定义数据进行携带所述第二约束条件的赋值操作以生成第二存储数据集合,所述第二存储数据集合包括所述第二约束条件、所述第二子节点所定义的数据以及所述第一存储数据集合。
10.根据权利要求9所述的电子设备,其特征在于,所述第二执行单元包括:
第一获取模块,用于获取所述第一子节点所定义的数据;
第一生成模块,用于生成所述第一存储数据集合,所述第一存储数据集合用于指示,在所述初始定义数据满足所述第一约束条件时,根据所述第一子节点所定义的数据对所述初始定义数据进行赋值,在所述初始定义数据不满足所述第一约束条件时,所述初始定义数据保持不变。
11.根据权利要求9或10所述的电子设备,其特征在于,所述第三执行单元包括:
第二获取模块,用于获取所述第二子节点所定义的数据;
第二生成模块,用于生成所述第二存储数据集合,所述第二存储数据集合用于指示,在所述初始定义数据满足所述第二约束条件时,根据所述第二子节点所定义的数据对所述初始定义数据进行赋值,在所述初始定义数据不满足所述第二约束条件时,根据所述第一存储数据集合对所述初始定义数据进行赋值。
12.根据权利要求9至11任一项所述的电子设备,其特征在于,所述确定单元还用于,确定执行树,所述执行树包括所述父节点、所述第一子节点、所述第二子节点以及所述结束节点,所述执行树所包括的所述父节点、所述第一子节点、所述第二子节点以及所述结束节点的代码执行顺序依次降低。
13.根据权利要求9至12任一项所述的电子设备,其特征在于,所述第二执行单元还用于,将所述第一存储数据集合写入至内存,以使所述内存的存储状态值为所述第一存储数据集合。
14.根据权利要求13所述的电子设备,其特征在于,所述第三执行单元还用于,将所述第二存储数据集合写入至所述内存,以使所述内存的存储状态值为所述第二存储数据集合。
15.根据权利要求14所述的电子设备,其特征在于,所述第一存储数据集合以条件选择算符的方式存储于所述内存中,所述第二存储数据集合以条件选择算符的方式存储于所述内存中。
16.根据权利要求9至15任一项所述的电子设备,其特征在于,所述第一子节点以及所述第二子节点中,有1个或0个为空。
17.一种电子设备,其特征在于,包括处理器和存储器,其中,
所述存储器中存有计算机程序产品;
所述处理器通过运行所述存储器中的所述计算机程序产品,以用于完成权利要求1至权利要求8任一项所述的符号执行方法。
18.一种计算机程序产品,其特征在于,当所述计算机产品被执行时,其用于执行权利要求1至权利要求8任一项所述的符号执行方法。
19.一种计算机可读存储介质,其特征在于,所述计算机可读存储介质中存储有指令,所述指令用于执行上述权利要求1至权利要求8任一项所述的符号执行方法。
Priority Applications (1)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
CN201811602959.7A CN111367786B (zh) | 2018-12-26 | 2018-12-26 | 一种符号执行方法、电子设备以及存储介质 |
Applications Claiming Priority (1)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
CN201811602959.7A CN111367786B (zh) | 2018-12-26 | 2018-12-26 | 一种符号执行方法、电子设备以及存储介质 |
Publications (2)
Publication Number | Publication Date |
---|---|
CN111367786A CN111367786A (zh) | 2020-07-03 |
CN111367786B true CN111367786B (zh) | 2021-06-08 |
Family
ID=71208958
Family Applications (1)
Application Number | Title | Priority Date | Filing Date |
---|---|---|---|
CN201811602959.7A Active CN111367786B (zh) | 2018-12-26 | 2018-12-26 | 一种符号执行方法、电子设备以及存储介质 |
Country Status (1)
Country | Link |
---|---|
CN (1) | CN111367786B (zh) |
Families Citing this family (5)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN112035379B (zh) * | 2020-09-09 | 2022-06-14 | 浙江大华技术股份有限公司 | 存储空间的使用方法、装置、存储介质以及电子装置 |
CN112564997A (zh) * | 2020-10-27 | 2021-03-26 | 图灵人工智能研究院(南京)有限公司 | 网络功能的验证方法、开发系统、计算机设备及存储介质 |
CN114238154B (zh) * | 2022-02-24 | 2022-05-06 | 湖南泛联新安信息科技有限公司 | 一种符号执行方法、单元测试方法、电子设备及存储介质 |
CN117829044B (zh) * | 2024-03-01 | 2024-05-14 | 上海合见工业软件集团有限公司 | 一种eda约束检测系统 |
CN118094548A (zh) * | 2024-03-28 | 2024-05-28 | 河南省电子规划研究院有限责任公司 | 一种软件依赖包的安全检测系统 |
Citations (2)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN102222035A (zh) * | 2011-07-25 | 2011-10-19 | 公安部第三研究所 | 基于符号执行技术的软件行为检测系统及检测方法 |
CN105243018A (zh) * | 2015-10-24 | 2016-01-13 | 北京航空航天大学 | 一种面向对象的类测试数据生成方法 |
Family Cites Families (1)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
US20020089436A1 (en) * | 2001-01-11 | 2002-07-11 | Shalom Yariv | Delta data compression and transport |
-
2018
- 2018-12-26 CN CN201811602959.7A patent/CN111367786B/zh active Active
Patent Citations (2)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN102222035A (zh) * | 2011-07-25 | 2011-10-19 | 公安部第三研究所 | 基于符号执行技术的软件行为检测系统及检测方法 |
CN105243018A (zh) * | 2015-10-24 | 2016-01-13 | 北京航空航天大学 | 一种面向对象的类测试数据生成方法 |
Non-Patent Citations (1)
Title |
---|
"一种基于抽象解释的二进制代码测试方法";周林;《信息工程大学学报》;20160607(第1期);第77-82页 * |
Also Published As
Publication number | Publication date |
---|---|
CN111367786A (zh) | 2020-07-03 |
Similar Documents
Publication | Publication Date | Title |
---|---|---|
CN111367786B (zh) | 一种符号执行方法、电子设备以及存储介质 | |
US9785532B2 (en) | Performance regression manager for large scale systems | |
Ali et al. | Generating test data from OCL constraints with search techniques | |
JP5209059B2 (ja) | ソース・コード処理方法、システム、及びプログラム | |
US8201142B2 (en) | Description language for structured graphs | |
Bogatinovski et al. | Self-supervised anomaly detection from distributed traces | |
CN104699601A (zh) | 用于执行状态机驱动的注入的方法和系统 | |
US8732676B1 (en) | System and method for generating unit test based on recorded execution paths | |
Assunção et al. | Establishing integration test orders of classes with several coupling measures | |
CN104937548A (zh) | 动态图的性能监视 | |
US11704186B2 (en) | Analysis of deep-level cause of fault of storage management | |
US8868381B2 (en) | Control system design simulation using switched linearization | |
CN104919427A (zh) | 动态组件性能监视 | |
Hierons et al. | Parallel algorithms for generating harmonised state identifiers and characterising sets | |
Liuying et al. | Test selection from UML statecharts | |
Sodhi et al. | Automatic construction and evaluation of performance skeletons | |
Lemieux et al. | Investigating program behavior using the texada LTL specifications miner | |
Szvetits et al. | Enhancing root cause analysis with runtime models and interactive visualizations | |
Gensh et al. | Modelling for systems with holistic fault tolerance | |
Chu et al. | An optimized model checking parallel algorithm based on CUDA | |
Wolf et al. | Specifying performance properties of parallel applications using compound events | |
JP6981087B2 (ja) | 情報処理装置、方法、及びプログラム | |
Goncharov et al. | Dynamic Actualization of Formal Model for Microcontrollers Software | |
Jin et al. | Graph-Centric Performance Analysis for Large-Scale Parallel Applications | |
Wiechmann | On improving the performance of pipe-and-filter architectures by adding support for self-adaptive task farms |
Legal Events
Date | Code | Title | Description |
---|---|---|---|
PB01 | Publication | ||
PB01 | Publication | ||
SE01 | Entry into force of request for substantive examination | ||
SE01 | Entry into force of request for substantive examination | ||
GR01 | Patent grant | ||
GR01 | Patent grant |