基于PAT树的符号执行工具的设计与实现硕士学位论文.docx
- 文档编号:9581376
- 上传时间:2023-02-05
- 格式:DOCX
- 页数:60
- 大小:333.58KB
基于PAT树的符号执行工具的设计与实现硕士学位论文.docx
《基于PAT树的符号执行工具的设计与实现硕士学位论文.docx》由会员分享,可在线阅读,更多相关《基于PAT树的符号执行工具的设计与实现硕士学位论文.docx(60页珍藏版)》请在冰豆网上搜索。
基于PAT树的符号执行工具的设计与实现硕士学位论文
硕士学位论文
基于PAT树的符号执行工具的设计与实现
AThesisSubmittedinPartialFulfillmentoftheRequirements
fortheDegreeofMasterofEngineering
ASymbolicExecutionToolbasedonProgramAnalysisTree
Candidate:
HuangJin
Major:
ComputerSoftwareandTheory
Supervisor:
Prof.LuYansheng
HuazhongUniversityofScienceandTechnology
Wuhan430074,P.R.China
Jun.,2007
独创性声明
本人声明所呈交的学位论文是我个人在导师指导下进行的研究工作及取得的研究成果。
尽我所知,除文中已经标明引用的内容外,本论文不包含任何其他个人或集体已经发表或撰写过的研究成果。
对本文的研究做出贡献的个人和集体,均已在文中以明确方式标明。
本人完全意识到,本声明的法律结果由本人承担。
学位论文作者签名:
日期:
2007 年 月 日
学位论文版权使用授权书
本学位论文作者完全了解学校有关保留、使用学位论文的规定,即:
学校有权保留并向国家有关部门或机构送交论文的复印件和电子版,允许论文被查阅和借阅。
本人授权华中科技大学可以将本学位论文的全部或部分内容编入有关数据库进行检索,可以采用影印、缩印或扫描等复制手段保存和汇编本学位论文。
本论文属于
保密□,在_____年解密后适用本授权书。
不保密□√。
(请在以上方框内打“√”)
学位论文作者签名:
指导教师签名:
日期:
2007年月日 日期:
2007年月 日
摘要
随着软件产业的不断发展,程序的规模越来越大,完全依靠手工进行测试的难度越来越大,这就需要一些辅助测试的自动化测试工具。
自动化测试工具能够自动地分析项目的源程序,自动地生成测试用例,并且达到一定的程序测试覆盖率,大大提高软件的可靠性和正确性,并且节约大量的人力和时间。
符号执行使用抽象的符号表示程序中变量的值,来模拟程序的执行。
符号执行的研究对于软件测试中测试用例的产生方法和程序证明理论研究,以及软件工程中逆向工程的研究都有重要的意义。
因此,无论在软件工程的理论研究,还是在软件测试自动化的工程实践中,符号执行都有进一步研究的价值。
目前国内外对符号执行进行了较深入的研究,并且已经开发出了一些工具。
但是符号执行的一些问题尚待解决,而且国内外缺乏针对Java的符号执行工具。
对数组的处理和模块调用的处理,仍旧是Java语言符号执行研究的难点。
此外,Java语言是一种面向对象的语言,其面向对象的复杂特性也增加了其符号执行研究的难度。
基于程序静态分析树PAT(ProgramAnalysisTree)树的符号执行方法是一种自动化的程序静态分析方法。
该方法通过分析Java源程序建立PAT树。
程序静态分析树能够对Java程序进行形式化的描述。
基于程序静态分析树的遍历方法是一种基于Java程序的逻辑结构的算法。
此外,符号执行系统的程序基本结构处理策略、符号计算方法和方法调用也是研究的重点,针对数组这个符号执行的难点也进行了相关的研究。
最后,通过一个针对Java程序的符号执行工具JSE(JavaSymbolicExecutor)分析表明了基于PAT树的符号执行在实践中的可行性。
关键字:
自动化测试,程序静态分析,符号执行,程序静态分析树
Abstract
Withtherapiddevelopmentofsoftwareindustry,programsarebecominglargerandmuchmorecomplexthaneverbefore.Duringthedevelopmentofsoftware,itistoodifficulttotestalltheprogramsmanually,soautomaticallytestingtoolsarenecessarytoanalysisprograms.Ifthetoolscananalysisprogramsautomatically,evengeneratetestdataautomaticallywithhighcoverageofprograms,thereliabilityofsoftwarewillbeimproveddramaticallyandconsiderableresourcewillbesaved.Symbolicexecutionsimulatesexecutionofprogramswithsymbolsinsteadofrealvalues.Symbolicexecutionisausefulmethodforprogramtestingandreverseengineering.
Manypeoplehavedonealotofresearchonsymbolicexecution.Somesymbolicexecutiontoolshavebeendeveloped.Stilltherearesomeproblemsofsymbolicexecutionneedtobesolved.Firstofall,nosymbolicexecutionsystemofJavaprogramhasbeendeveloped.Secondly,solutionsforarrayandmodulecallarestilldifficultiesofJavasymbolicexecution.Finally,thecomplexityofJavaincreasesthedifficultyofthesymbolicexecutionimplement.
ThesymbolicexecutionbasedonPAT(programanalysistree)isanautomaticprogramstaticanalysismethod,whichcananalysistheJavaprogram.Also,avisitingmethodisdesignedforPAT.Moreover,someresearchesonsymbolicexecutionhavebeendone.Attheendofthisthesis,asymbolicexecutiontoolcalledJSE(JavaSymbolicExecutor)isdeveloped.
Keywords:
AutomaticallyTesting,StaticAnalysis,SymbolicExecution,ProgramAnalysisTree
1绪论
本章首先介绍了软件测试中符号执行系统的研究背景、意义和主要研究内容,概述了符号执行系统的任务、设计原则和实现难点,然后列举了迄今为止具有代表性的系统和框架,以及它们的优缺点,接着指出了本文的研究重点:
程序符号执行系统设计与实现。
最后指出其存在的不足,并提出了改进的方案。
1.1研究背景
随着信息技术的飞速发展,软件产品应用到了人类社会生活中的各个领域,但是各种软件故障也对社会带来了极大的经济损失,甚至产生了一定的破坏作用。
特别是对于安全关键系统(SafetyCriticalSystem,如民航订票系统、银行结算系统、自动飞行控制软件、军事防御和核电站安全控制系统等)对系统安全性有特殊的要求,而且软件系统本身复杂度高。
针对这种需求,以软件测试为中心的质量保障技术在软件生产中得到了迅速的发展和应用,软件测试成为发现软件故障,保证软件质量,提高软件可靠性的主要手段。
有数据表明,软件测试在软件开发中所占用的时间和资源一般在40%至70%。
随着软件技术不断发展,现代软件系统发展极其迅速,这就对软件测试技术提出了更高的要求。
软件测试技术的进步能够极大的减少软件工程中投入的时间,人力和物力,因此对软件测试技术的研究显得尤其重要。
IEEE把软件测试定义为:
从无限大的执行域中恰当地选取一组有限测试用例,对照程序已经定义的预期行为,动态地检验程序的行为。
实际上,软件测试是软件过程的一个核心工作流,贯穿于整个软件开发过程始末。
软件测试过程包含了测试计划的制定、测试大纲的编写、测试用例的设计与生成、测试的实施、测试结果与问题的分析和报告、以及软件测试的管理等工作。
软件测试有两个基本要求,一是要验证程序符合规约的要求;二是要证明此验证过程是可信的。
前者强调软件测试是一个软件验证工程,涵盖软件开发的各个方面,包括从需求说明到概要设计、详细设计乃至编程和执行的所有阶段。
具体来说软件测试需要检查系统的执行是否正确,包括三个方面:
功能方面程序必须能够完成约定的功能,例如实时性要求;输入和输出方面要求程序对给定的输入须有正确的输出,包括例外情况;对外界的影响方面同具体的环境有关,例如程序内存管理、文件管理,以及对其它应用程序的执行干扰等。
对于后者,测试需要一个充分性准则,表明到什么程度测试可以终止并取得可信的结果。
程序规约(Specification)是测试的基础。
规约一般在程序编写之前就己经明确并规定了程序应该做什么。
测试是在规则的指导下选择一系列测试用例,并在执行测试用例时观察程序行为是否符合规约的要求。
不是所有的程序规约和结构都必须被测试用例所覆盖,因此需要一个程序的正确性定义和测试的充分性验证准则。
软件测试技术可以分为静态测试和动态测试[1]。
静态测试是不执行程序代码而寻找程序代码中可能存在的缺陷或评估程序代码的过程。
动态测试通过在抽样测试数据上运行程序来检验程序的动态行为和运行结果以发现缺陷。
测试也分为结构性测试(又称白盒测试)、功能性测试(黑盒测试)、以及程序与规约相结合的测试(灰盒测试)。
白盒测试包括控制流测试和数据流测试两类主要技术以及域测试、符号执行(SymbolicExecution)、程序插桩和变异测试等其它技术。
黑盒测试又包括:
等价类划分、因果图、判定表、边值分析、组合覆盖测试和状态测试等。
灰盒测试综合考虑软件的规范和程序的内部结构来生成测试数据。
静态测试中大量使用程序静态分析技术[2]。
程序静态分析技术是指不编译运行待测试程序,而是通过对程序源代码进行分析以发现其中的错误。
程序静态分析的目标不是证明程序完全正确,而是作为动态测试的补充,在程序运行前尽可能多的发现其中隐含的错误,提高程序的可靠性和健壮性[3]。
事实上在很多相当成熟的系统中包含着错误,只凭测试人员手工很难找到这些错误,而通过静态测试发现了现存系统的很多错误[4~6]。
程序静态分析的方法主要有以下几种:
(1)符号执行[7,8]。
符号执行的基本思想是,用抽象的符号表示程序中变量的值,来模拟程序的执行。
该方法很好的克服了其他测试技术中不能确定程序中变量的值的问题。
符号执行常常使用于对路径敏感的程序分析中。
符号执行结合约束求解方法理论上可以精确地静态模拟程序的执行,因此约束求解工具的接受能力决定了分析程序和发现错误的能力。
(2)定理证明[9]。
自动定理证明是基于语意的程序分析特别是程序验证中常用到的技术。
但是采用消解原理的定理证明器一般并不适合于程序分析,通常使用各种判定过程来判断公式是否为定理。
(3)类型推导。
类型推导指的是由机器自动地推导出程序中变量和函数的类型,它的思想是将程序中的数据划分成不同的集合,再利用类型理论中的算法进行分析。
类型推导适用于控制流无关的分析,能够处理大规模的程序。
(4)基于规则的检查。
在面向不同应用的程序中,存在不同的编程规则。
基于规则的检查使用规则处理器,将规则转换成内部表示,将其应用于程序分析。
基于规则的分析方法的优点是能够针对不同的系统采用不同的规则进行分析。
缺点是受到规则描述机制的局限。
(5)模型检测。
模型检测是一种验证有限状态并发系统的方法。
它是基于有限状态系统构造和有向图等抽象模型的。
它的难点在于如何避免状态空间的爆炸。
以上几种方法之间有一定的联系。
类型推导和模型检测都是对程序的抽象。
符号执行和类型推导都有程序产生约束,只是约束的形式不同:
符号执行的约束形式是布尔表达式以及线性等式和不等式;类型推导的约束形式是集合关系表达式。
上面这些方法形式各异,各有相关的分析工具[10~14],分别实现了各自的理论的将价值。
采用新型的编程语言和开发方式,可以极大的提高软件系统的开发效率,同时也能明显减少错误的引入。
Java语言是当今一种主流的软件系统开发语言,具有较高的可靠性。
Java使用早期问题检查机制和运行时检查机制,并且Java的语言模型避免了拙劣的指针和内存分配错误导致的内存泄漏错误。
其次,Java被设计用于网络/分布式环境,具有一定的安全机制,比如禁止运行时堆栈溢出,禁止破坏运行空间外内存等。
但是Java语言仍旧无法避免程序设计错误等原因带来的软件错误,例如逻辑错误。
因此,有必要对Java语言软件测试技术进行一定的研究。
1.2符号执行系统的意义
符号执行[15](symbolicexecution)的思想早已提出。
符号执行的基本思想是:
用抽象的符号表示程序中变量的值,来模拟程序的执行。
该方法很好地克服了在静态测试时不能确定程序中变量的值的问题。
符号执行常常在对路径敏感的程序分析[16,17]中使用。
对符号执行的研究也有很多。
通常意义下的程序执行是给出具体的输入数据使得程序能够沿着某一特定路径执行并输出与之对应的具体结果。
然而符号执行的目的在于分析程序中变量之间的约束关系,不需要指定具体的输入数据,将变量作为代数中的抽象符号处理,结合程序的约束条件进行推理,结果是输出一些描述变量间关系的表达式。
在符号执行的过程中,控制流图中的分支导致了对于变量的不同的约束条件,而这些约束条件就描述了相应路径的测试数据间的约束关系。
符号执行的研究无论是对软件工程本身的研究,还是对实际工程中测试技术的发展,都有比较重要的意义[18,19]。
首先,符号执行和约束求解方法的研究产生了基于符号执行和约束求解的测试用例产生标准和方法[20]。
其次,符号执行方法的研究中对于从代码还原状态图的研究对软件工程中的逆向工程有较大的促进作用。
此外,对于软件测试的程序证明(programproving)理论的研究也有重要的意义[21]。
具体来说符号执行的应用主要有以下几个方面:
1.产生测试用例
符号执行最重要的一个应用就是可以自动生成测试用例[22~24]。
符号执行输入符号值和路径选择,然后符号执行程序的选定路径,得到符号执行的结果以及路径选择条件集合。
对于软件测试来说,可以使用真实值代替符号输入,那么所选用的真实值就是一组测试数据。
其中,真实值产生的依据就是符号执行程序某路径的路径选择条件。
因此,我们在软件测试中,可以利用符号执行,设计一些自动生成工具,遍历符号的执行路径,根据不同路径的选择条件,自动的产生测试用例,而且使用这种产生测试用例的方法,测试的覆盖率很高[25]。
2.程序证明
最著名的程序证明[26]方法是由Floyd提出基于断言机制的“诱导断言确认法”。
该方法将断言设置在程序模块的开始和结尾,那么判断一个模块或者一段程序正确与否的标准就是模块开始处的断言必须要保证模块结束处断言的正确性,否则程序模块出现错误。
例如在某个程序中要求变量A满足A>4且A<10,那么我们将断言插入程序中。
在符号执行过程中,我们可以将路径执行条件加入程序的断言中去。
当一个断言中包含路径选择条件的程序符号执行时,如果路径选择条件与断言一致,那么可以发现程序该路径是可达的。
反之,如果路径选择条件与断言矛盾,可以很容易的发现路径是不可达的。
3.符号调试
符号执行本身可以模拟程序的执行过程,因此符号执行可以用于程序的调试[7]技术。
通常意义上的程序跟踪调试只能跟踪显示程序运行过程中变量的当前真实值。
但是一个基于符号执行的调试工具能够跟踪显示变量的符号表达式,这样变量的意义就更加明显。
1.3符号执行系统的研究现状
对于符号执行的研究,目前不仅已经有了一定的理论成果[27~29],而且还针对各种语言开发出了许多的工具[30~32]。
本节主要介绍几个有代表性的系统,并针对各个系统进行相应的评价。
1.3.1交互符号执行系统EFFIGY
EFFIGY是一个由IBMThomasJ.WatsonResearchCenter的JamesC.King等人研发的符号执行系统,针对程序的调试和测试的交互性符号执行器(InteractiveSymbolicExecutor),能处理PL/I型语言的程序。
EFFIGY是第一个使用符号执行的系统。
它利用符号执行的特性,用于程序的开发和测试。
该系统具有一定的适应性,其最大的特点是具有一定的交互性。
符号执行可以得到程序路径的符号结果,并且在系统中逐行显示变量的符号值。
EFFIGY功能上最大的诟病在于没有提供一个程序路径的流程图,这样不便于使用者确定路径的执行情况。
同时,它没有提供一个路径选择的策略,而必须由使用者制定测试的策略,选则路径,例如每一次循环,都要选择是否继续循环。
这样就加大了使用者的工作量。
该系统没有直接提出模块调用的处理方法。
对于数组和指针,该系统也没有涉及。
1.3.2功能全面的符号执行系统SELECT
这个试验系统主要实现的功能包括:
符号执行程序遍历所有可能的程序路径;简化符号执行结果;自动产生测试用例;用于程序的符号调试。
SELECT具有一定的判断程序路径可达性的能力。
这个系统本身就是设计用于根据设定的算法自动产生路径选择策略,从而使得符号执行能够覆盖程序的每一个分支。
随着符号执行的进行,每添加一条程序分支,就计算程序分支的路径选择条件,进而判断路径的可达性。
SELECT的分析器能够处理线性和非线性的不等式,并且根据结果产生测试用例。
对于存在大量循环的程序的处理,SELECT使用交互性的策略,根据使用者的需求设定循环的次数,然后系统自动更新路径选择条件和变量的符号表达式,知道循环结束。
SELECT使用预备策略处理模块调用。
当模块满足复用的条件时,即不存在不确定的过程,例如循环,那么在符号执行前单独处理每一个子模块,记录下符号执行结果和路径选择条件。
当子模块被调用时,直接使用子模块的处理结果。
但是这样会导致程序可选择路径的数量爆炸,影响符号执行的运行效率。
1.3.3单元测试引擎CUTE
CUTE[33]是近年来出现的一个针对C语言和Java语言的单元测试工具。
该工具能够系统的自动的测试面向过程的C语言(包含指针)和并行的Java程序。
CUTE结合了具体执行和符号执行的优点,避免了随机测试的低效性。
CUTE通过具体执行和符号执行相结合的方式执行待测程序。
它的符号执行的方式区别传统的符号执行方式,符号执行是在程序具体执行的基础上进行的。
在CUTE的执行过程当中,收集程序执行路径的路径选择条件,在程序某条路径的结尾,处理收集到的一组符号约束条件,产生该路径的测试用例。
CUTE的算法首先随机产生一个具体的输入,然后循环执行以下过程:
(1)使用产生的输入执行代码,同时计算路径符号约束条件;
(2)如果遇到程序分支,随机产生一个具体输入;
(3)如果当前程序分支执行完成,那么退回前一个分支节点,处理路径的符号约束,计算出执行该分支节点的其他未执行路径的具体输入值。
CUTE采用了深度优先遍历的策略,遍历了整个程序的分支。
更重要的是,算法使用的是具体值来执行程序,因此发现的程序错误具有较高的可信度。
为了验证CUTE的正确性,进行了相关的测试实验。
一个是比较流行的用C语言编写的数据结构库SGLIB,另一个是著名的Sun公司在JDK1.4中被广泛使用的安全的线程收集框架。
使用CUTE对SGLIB进行单元测试,在三秒钟内发现了两个错误。
一个错误是在一个双链表库中发现的,一个非空的链表链接到了一空链表中去了。
另一个错误是一个死循环。
后来SGLIB的开发者证实了错误的存在。
使用JCUTE对安全的线程收集框架进行测试,意外的发现了潜在的多线程之间的竞争,死锁,不能被捕获的异常和死循环。
这再一次的证明了CUTE的算法的正确性。
1.3.4现有研究总结
对于符号执行研究的难点,国内外的许多学者有了一些初步的研究。
国内特别是中科院的张健等研究员对于符号执行的指针,结构变量,路径可达性问题和约束求解问题有一定的研究。
具体来说,符号执行研究存在的主要难题有以下四个:
1.循环(loop)的处理
如果程序中循环[7]的次数是未知的,或者说是动态的取决于程序的输入或者状态,那么符号执行是无法获知执行的路径的,会造成符号执行处理过程复杂化。
如果循环次数太多,那么符号执行也是不可行的。
因此对于循环,主要采取交互式的方式,手动设置循环次数上限或者交互式设置循环次数,处理符号执行中的循环执行次数不确定的问题。
2.模块调用(modulecall)的处理
程序中存在着大量的模块调用[7],如函数的调用。
但是这样的调用会造成符号执行处理过程的爆炸[34],那么对于符号执行也是不可行的。
处理符号执行中的模块调用主要有两种策略:
动态扩展策略和预处理策略。
前者在对某个模块符号执行时,实时地对某个模块进行符号执行,它的优点是符号执行过程灵活,且存储空间需求低,但是消耗了一定的执行时间。
后者在针对某个程序符号执行时前,已经将所有模块进行了符号执行,并将符号执行的结果纪录下来,以后在符号执行过程中如果需要调用模块,只需要调用该模块的符号执行结果。
它的优点是一次执行,永久使用。
但是它不适用于存在不确定元素,如循环和数组的模块,灵活性差,且对于大型程序,占用大量的存储空间。
3.数组(array)的处理
对于数组[35],如果程序中出现了下标是变量的数组成员,比如A[i],其中i是一个变量,那么符号执行时,对A[i]的操作,比如赋值,处理起来就会十分复杂。
对数组元素的混淆,已经提出了一种处理符号执行中数组元素混淆的方法,通过转换存在数组元素混淆的代码段,可以被一般的符号执行工具识别。
此外,中科院软件所的张健提出了基于形式转换的处理数组和指针的方法,设计了工具PAT,实现了对数组和指针元素的操作。
4.不可达路径(infeasiblepath)的处理
符号执行研究中的不可达路径问题[36,37]实际上是基于约束性问题[38]的。
由于程序中存在着大量的不可达路径,符号执行揭示这些不可达路径,从而测试程序分支的正确性。
因此,对不可达路径的研究也是十分有意义的。
目前中科院的张健对此进行了一定的研究,给出了分离路径执行条件和针对整形和布尔型的线性条件约束求解的方法,提出了基于程序流图的搜索算法,并且实现了约束求解工具BoNuS[2]。
1.4论文的组织结构
本文符号执行系统的研究与实现分为理论研究和技术实现这两个方面。
理论研究的主要内容包括建立程序静态分析的中间表示模型和建立描述符号执行的行为模型。
符号执行系统的技术实
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 基于 PAT 符号 执行 工具 设计 实现 硕士学位 论文