代码测试(共5篇)
代码测试 篇1
1 引言
软件测试贯穿于软件的整个生命周期, 是软件生存周期必不可少的一部分, 软件开发从总体的需求设计到具体的代码编写, 每一个阶段都伴随着软件测试, 阶段不同, 采用的测试方法和策略也各不相同。如何保证在总体的需求分析和详细设计正确的情况下尽量减少代码编写过程中所犯的错误, 是测试领域研究的内容之一。
从是否执行程序的角度来讲, 软件测试方法分为两大类, 即静态方法和动态方法[1]。静态方法的主要特征是不利用计算机运行被测试的程序, 而是采用其它手段达到检测的目的。代码检测就属于静态方法的一种, 至于静态分析在软件测试中究竟占据什么地位, 许多人有不同的见解。有些人认为静态分析只是进行动态分析的预处理工作, 静态分析并不是要找出程序中的错误, 因为编译系统已经能够做到这一点了。实际上, 这种看法是片面的, 尽管编译系统能发现某些程序错误, 但这些远非软件中存在的大部分错误, 而且也仅仅是语法方面的错误, 对于程序中潜在的故障, 很多是编译程序检测不到的, 因此静态分析的查错功能是编译程序不能代替的。
代码自动检测就是在程序经过调试和编译通过以后, 运用某种测试技术对源程序进行静态分析, 从而发现程序中存在的错误。所用的程序设计语言不同, 检测到的故障各不相同, 本文针对现阶段比较通用的程序设计语言JAVA为例, 对程序可能出现的故障进行分析。本文在以下内容中介绍了代码自动检测技术能检测到的各种故障, 随后对检测原理进行了深入剖析, 最后设计了软件测试工具, 并在工程中进行了实践。
2 检测的故障类型
代码自动检测技术能发现程序中存在的多类错误, 然而编码中采用的设计语言不同, 检测到的错误不同, 本文以JAVA程序设计语言为例, 阐述能发现的故障类型。JAVA是非常有吸引力的面向对象的编程语言, 也是当前最流行的网络编程语言, 在很多高校, JAVA程序设计已成为信息类相关专业学生的必修科目, 然而它规定了严格的语法, 但又有它的灵活性, 它的对象性及接口的多样性增加了程序编写的灵活性, 程序员可以任意发挥他们的编程技巧, 这大大增加了程序的灵活性, 然而这种灵活性又增加了程序的不可预见性, 这直接导致了故障的发生。譬如数组越界是缓冲区溢出故障类型中的一种最常见的故障, 它是由于对数组下标的操作越过了下标的范围引起的, 数组越界在使用数组类型进行程序设计的软件中普遍存在。另外还有JAVA提供的一些关于字符处理的函数, 虽然提供了这方面的功能, 但没有对参数范围进行限制和检查, 这也很容易导致错误的发生。以上这些故障采用一般的方法是很难发现的, 因此必须采用一些特殊的检测方法对软件进行检测。
下面这些故障是本文所能检测到的:
⑴内存泄漏。JAVA语言中的内存泄漏与传统语言的内存泄漏是十分不同的, 它是指内存对象不再需要时, 但却仍被程序无意识地、错误地保持或引用而导致GC无法回收对象所占用的内存空间。在GC看来, 它们还是“有用”的, 从而导致内存泄漏。
⑵数组越界。数组越界顾名思义就是数组超出了原先设定的范围, 导致出现了意想不到的结果。
⑶中文乱码。JAVA语言内部采用UNICODE编码, 所以在JAVA程序运行时, 就存在着一个从UNICODE编码和对应的操作系统及浏览器支持的编码格式转换输入、输出的问题, 这个转换过程有着一系列的步骤, 如果其中任何一步出错, 则显示出来的汉字就会出是乱码。
⑷变量未初始化。变量定义后必须被初始化, 未初始化的变量的值不确定, 使用它会使程序出现不正确的结果, 甚至导致程序出现异常。
⑸不可达代码。不可达代码是指永远执行不到的代码。
3 静态分析技术
近年来由于测试技术的发展, 很多人开始对静态测试进行研究, 并提出了很多的理论和方法, 如C.Cowan[2]等人开发了一个缓冲区溢出故障测试工具, David Wagner[3]也给出了一种程序溢出故障的静态检测方法, David Evans[4]也给出了一种对动态内存故障进行静态测试的新方法。这些测试方法的提出在很大程度上丰富了软件测试的理论, 加快了软件测试发展的步伐, 并在实践应用中取得了很好的效果。这里我们就给出对代码进行自动分析, 从而对故障进行检测的一种新方法, 并进行了工具的开发, 在工程应用中取得了很好的效果。
代码自动检测方法的核心是对程序源代码进行静态分析, 运用编译技术把程序翻译成一种树的中间表示, 这种树叫语法树[5], 而后生成与语法树相对应的程序的控制流图, 然后运用故障规则对程序进行检测和故障定位。
3.1 语法树
语法树是程序代码的一种树形表示, 是程序经过翻译后的一种中间表示形式。依据JAVA语言的语法规则, 语法分析器接受词法分析产生的记号串, 并依照相应的规则将记号组织成具有确切含义的语句, 并构造相应的语法树。譬如赋值语句position=initial+rate*60可以用图1的语法树表示。
其中根节点是赋值语句, 叶结点表示终结符, 即标识符。
语法树是编译程序在经过语法分析以后得到的源程序的另外一种表示, 语法分析的结果是生成语法树, 每一个语法规则对应一个相应的处理函数, 并作为树的一个节点挂在语法树上, 提供对外的接口。由语法树可以生成程序的控制流图和变量的定义使用链, 同时定义一些相应的数据结构, 为下一步的错误查找作准备。
3.2 控制流图
程序流程图是人们最为熟悉的一种程序控制结构的图形表示法, 在这种图上的框内表明了处理要求或条件, 这些在软件测试中进行路径分析时是不重要的, 需要对其进行简化。
下面以一段程序为例, 简要说明控制流图的构建。
程序段为:
对应的流程图及控制流图如下:
其中 (a) 是一个含有两出口判断的程序流程图, 把它简化成 (b) 的形式, 称这种简化了的流程图为控制流图。
在控制流图中只有两种图形符号, 它们是:
①节点:以标有编号的圆圈表示。它代表了程序流程图中矩形框所表示的处理、菱形表示的两至多出口判断以及两至多条流线相交的汇合点。
②控制流线或弧:以箭头表示。它与程序流程图中的流线是一致的, 表明了控制的顺序。为方便讨论, 控制流线通常标有名字。
用控制流图表示程序的结构简明易懂, 是软件测试阶段一个很好的工具, 其中一个很好的应用就是在白盒测试阶段依据源程序生成程序的控制流图, 遍历控制流图的路径, 对程序进行路径测试分析。由于控制流图仅有一个入口和一个出口, 从入口进入的每一条路径都能到达出口节点, 因此控制流图是一个有向图。
3.3 代码分析过程
代码自动分析过程就是构造程序的语法树和控制流图以及故障匹配的过程。
(1) 构造程序的语法树。语法树是进行故障分析的基础。分析器读入
源程序, 经过词法分析和语法分析, 产生出与程序对应的语法树, 程序的相关信息都可以反映在语法树上。
(2) 产生控制流图。语法树是程序的另外一种表示, 是一种中间形式,
然而这种树的结构并不能反映程序的控制结构, 因此需要构造程序的控制流图, 来反映程序的控制流程。程序的控制流图与语法树是相对应的, 控制流图的每一个节点对应语法树上的一个语句节点, 从控制流图的接口可以方便的访问与之对应的语法树节点, 从而获得相关的信息, 同样的从语法树的语句节点也可以很方便的访问到控制流图的相应节点。以上已通过例子对语法树和控制流图的构造进行了介绍, 如图1和图2所示。
(3) 故障检测。从控制流图的根节点出发, 依次访问控制流图的各个
节点, 并通过控制流图提供的接口访问与其对应的语法树节点, 而后依次遍历它的每一个子节点, 在遍历过程中如果发现与故障模式相匹配的地方, 则将故障输出。
4 自动检测工具的实现
由以上的方法可知, 代码自动检测的核心是对源程序进行词法分析和语法分析, 生成相应的语法树和控制流图, 也就是设计一个编译系统。其整体测试框架为:
(1) 预编译:由于源程序中存在宏定义、文件包含和条件编译等预处理命令, 因此在进行词法分析前必须进行预处理, 将宏进行展开, 这样有利于变量的查找。
(2) 词法分析:将预编译阶段产生的中间代码分解成单独的词的表示, 形成初步的符号表, 为语法分析作准备, 表的结构主要有:标识符表、类型表、关键字表、常数表、运算符表和分界符表。标识符表中包含有利于错误查找的一些相关信息, 如:位置、行号、错误类型, 这些信息对于错误的查找和定位都有十分重要的作用。
(3) 语法分析:这一步主要是将输入字符串识别为单词符号流, 这里主要是找出变量声明语句, 并相应的分离出指针变量和数组变量。按照标准的JAVA语法规则, 对源程序作进一步分析, 比如什么是变量定义, 什么是赋值语句, 什么是函数等等。语法分析的结果是生成语法树, 每一个语法规则对应一个相应的处理函数, 并作为树的一个节点挂在语法树上, 提供对外的接口。由语法树进一步生成程序的控制流图, 同时定义一些相应的数据结构, 为下一步的故障检测作准备, 同时在这一过程也逐渐添加和细化符号表的一些相关信息。
(4) 故障检测:查找程序中可能出现的错误。依据程序的控制流图, 依次遍历语法树的各个节点, 匹配欲查找的错误, 如错误找到, 则将错误信息记录到数据库中, 最后得到数据库文件。数据库文件记录测试过程中得到的一些相关信息, 如出现错误的变量名、出现错误的行号、该行字符串、错误类型等。由数据库文件生成故障信息报告, 将故障信息反馈给用户, 用户根据故障报告进行程序更新和维护。
5 实验结果分析
以上给出了代码检测的一种自动分析方法, 运用该方法我们进行了测试系统的开发, 并针对一些不同领域的具体的软件项目进行了测试, 部分测试结果如表1:
表格中的文件大小以M为单位, ML:内存泄漏故障;OOB:数组越界故障;UV:未初始化变量故障;DC:死码故障;
以上表格中的内容是我们测试数据的一部分, 从表格中的数据可知, 这几类故障在软件项目中普遍存在, 只是项目不同, 故障分配的概率不同, 因此开发面向故障的软件测试工具十分必要。
6 结论
以往的代码审查通常是在代码完成以后, 通过人工的劳动对代码进行走读, 这种检查不仅费时费力, 而且很难发现其中的错误, 因此不仅效率低, 而且效果比较差。本文提出的这种代码检测方法通过对源程序进行分析, 匹配故障查找模式, 结合程序的控制流图和相应的语法树, 自动查找程序中存在的错误, 不仅节省时间, 效率高, 在检测过程中不需要人为的干预, 只需要对检测的结果进行确认, 因此自动化程度高, 是代码检测的一种好方法。本文通过应用这种静态测试方法, 进行了软件测试工具的开发, 并能检查出软件中存在的六种故障, 然而这几种故障并不能代表所有的故障类型, 在以后的工作中, 我们将继续拓展故障类型和规则, 争取使这种测试方法能检测出更多的故障, 使其更加完善。
参考文献
[1]郑人杰.计算机软件测试技术[M].北京:清华大学出版社, 1992.
[2]赵鹏宇, 李建茹, 宫云战.Java语言中数组越界故障的静态测试研究.
[2]朱颖芳.关于JAVA内存泄漏问题的探讨.电脑知识与技术, 2006年第32期.
[3]N.Dor, M.Rodeh, and M.Sagiv.Cssv:Towards a realistic tool for statically detecting all buffer overflows in c[C].In Proceedings of the ACM SIGPLAN 2003 Conference on Programming Language Design and Implementation, 2003:155–167.
[4]D.Wagner, J.Foster, E.Brewer, and A.Aiken.A first step towards automated detection of buffer overrun vulnerabilities[C].In Proceedings of the Network and Distributed Systems Security Symposium, 2000:3–17.
[5]David Evans.Static Detection of Dynamic Memory Errors[C].USA:ACM Conference on Programming Language Design and Implementation, 1996:44–52.
[6]A.V.Aho, R.Sethi, R., and J.D.Ullman.Compilers Principles, Techniques, and Tools[M].America:Addison Wesley, 1986.
代码测试 篇2
2. 测试尽在掌握——Visual unit。
3. 准时准确,你准备好了吗?——Visual unit!
4. 我们只负责您做的好更好!
5. 试试,原来工作就是这样简单。
6. 十八般武艺,轻松解决测试问题!
代码测试 篇3
云计算是将虚拟化的资源在互联网上以动态伸缩的形式提供可用的、 便捷的、 按需的相关服务。 云计算的优势在于提供少量的管理工作而使用大量的共享资源, 它融合了网格计算、 效用计算、 分布式计算、 并行计算、 网络存储、 虚拟化、 负载均衡等技术。 在当前阶段, 云计算可以分为私有云、公有云和混合云, 其中私有云是专为一个客户单独构建的, 一般它的服务对象是一个企业, 它被部署在企业防火墙之内, 也可能被部署在一个安全的主机托管场所[1]。
软件安全测试作为新的测试点在近年来倍受重视, 软件安全测试的目的是避免由于软件开发及软件应用所带来的潜在风险, 进而保护财产不受侵害。 目前国内较多的软件安全测试侧重于网络安全, 在源代码安全方面涉及不多; 在已有的源代码安全测试方面基本上还在依靠工具进行代码扫描的阶段, 但是, 因为目前国内所具有的源代码安全测试工具价格不菲, 不可能大量购买, 这就限制了源代码安全测试的效率, 基于此, 提出一种在私有云技术基础上, 结合源代码安全测试工具建立源代码安全测试的云平台。
2 源代码安全测试云平台的实现
源代码安全测试云平台是将云计算和源代码测试相结合的一种新型的测试方式, 它关键是需要建立私有云平台和购买源代码安全测试工具, 现阶段的云平台搭建主要有CloudStack和Open Stack两种方式, 这些云计算平台与单机操作系统类似, 主要完成向上提供计算、 存储等资源接口, 向下控制底层资源的功能, 它的关键技术主要是 “资源池” 管理技术和向下提供存储计算等分布式服务以及数据管理。 在私有云的建设上, 结合Cloud Stack方式提出以Web+分布式部署的方式, 这种方式更加灵活、 简单、 方便、 高效。 以下详细介绍私有云平台搭建方案。
考虑到管理方便, 搭建的私有云平台服务器可以建立在企业内部, 这样可以有效控制使用范围, 更好地实现安全管理, 更好地实现对源代码的保密。 搭建服务器, 使用适当的管理软件, 使用分布式部署, 可以有效降低服务器的要求。实现方法是结合Cloud Stack方式, 运用Web+分布式部署原理, 将代码的上传及报告的下载分布在各个业务电脑, 如果为了追求更加灵活的服务, 可以设置虚拟机服务器, 这样虚拟机和基础服务器没有依赖关系, 虚拟机可以实现迁移, 实现在物理服务器之间移动而不需要中断运行。
在这里, 假设搭建的私有云平台服务器是虚拟机系统, 可以按照不同的需求安装不同的虚拟机系统。 目前, 主流的服务器虚拟机系统有Vmware, Critrix Xen Server, Microsoft Hyper-V和KVM。 在这里建议使用Vmware, 它可以实现完全的虚拟化, 在任何操作系统下独立运行, 但是对性能要求较高。
云平台部署应用程序时, 需要系统配置管理工具, 目前应用较多的是App Stack。 App Stack是一款非常实用的云应用管理平台, 它可以简化私有云中配置和管理复杂的应用程序。App Stack软件采用数据模型驱动技术, 它可以将大多数应用程序的管理任务自动化, 可以更新运行中实例的系统参数和配置, 不需要用户手动更新虚拟服务器的配置文件[2]。
当前主流的Webserver有kangleweb、 nginx、 Apcche 3 种, kangleweb具有跨平台、 功能强大、 安全稳定、 易操作等优点, 它更适合虚拟机使用, 实现虚拟主机独立进程、 独立身份运行。 Kangleweb的用户之间实现隔离, 用户之间不会交叉影响。 Nginx是一款轻量级的Web服务器/反向代理服务器及电子邮件 (IMAP/POP3) 代理服务器, 它具有占有内存少, 并发能力强等优点。 Apache使用最为广泛, 它几乎可以运行在任何计算机平台上。 在这里, 推荐使用Apache服务器系统, 如图1 所示。
在服务器集成源代码安全测试工具, 在进行测试时, 用户通过云入口, 直接提交测试代码, 创建测试任务, 云平台会启动任务分配机制, 任务排队机制进行处理。 测试数据全部收集到测试数据库中进行存取, 如图2 所示。
3 平台实现的功能
源代码安全测试平台不仅可以实现源代码的安全测试, 还可以实现项目管理、 测试管理、 系统管理等功能。 在客户端, 不需要安装源代码安全测试工具, 也不需要搭建测试所需要的特定环境, 只需有Web插件即可。
在私有云平台的项目管理方面, 可以清楚地看到各个测试项目的名称、 版本、 开发语言、 语言版本、 编码模式、 测试人员、 所属部门、 测试时间等有效信息。 在客户端查看测试结果, 可以看到问题代码, 问题分析, 问题解决建议, 问题严重程度, 测试结果分析, 如果平台允许, 还可以自定义报告模版。 其他平台可以实现诸如部门管理、 机器管理、 计费管理、 模版管理、 规则库管理、 任务管理等功能。 总的来说, 源代码安全测试云平台可以实现较多的综合功能, 具有如下优势:
(1) 无限使用:不再受工具License限制。
(2) 自动化:测试自动化。
(3) 测试标准: 企业制定的安全测试标准, 贯彻在测试过程中。
(4) 结果查看方便:测试结果远程Web方式查看。
(5) 统计:对历史测试结果统计分析。
4 结语
源代码安全测试云平台不仅可以测试源代码安全, 如果集成进去相应的测试工具, 还可以实现其他的测试功能, 例如集成App Scan, 就可以实现一些黑盒测试, 这种云平台适应性很强, 适合大多数的企业使用, 而且建立的成本不高, 当然, 因为没有实际使用, 它仍然存在着一些未知的问题, 希望今后继续探索, 使它更加完善。
参考文献
[1]魏志华, 赵强强.构建企业私有云软件测试平台[J].电子技术与软件工程, 2015, 09:63-64.
代码测试 篇4
随着智能手机与大众工作生活的关系逐渐密切, 各类安全问题也日益凸显。僵尸病毒、收费陷阱、隐私窃取、流氓软件、垃圾短信等负面新闻不断出现, 影响了用户的消费信心, 阻碍了移动互联网产业的健康发展。
程序开发人员常说“源代码不会撒谎”, 意思是不管文档怎样记录、广告如何宣传, 应用软件表现出来的任何行为最终都能在源代码中找到答案。但是, 为了保护商业机密, 很多软件在进行第三方安全测试时并不提供源代码, 因此在常规的黑盒测试之外, 只能直接从程序的二进制代码入手进行逆向分析[1]。从测试的角度看, 作为“固化的源代码”, 二进制代码更不会撒谎, 这是因为:
1. 使用不同的编译选项, 可以从同一份源代码生成千差万别的二进制代码;
2.无论怎样调整编译选项, 也难以从逻辑行为不同的源代码生成运行于同一目标平台的完全相同的二进制代码。
在这个意义上, 二进制代码确切标识了用来生成它的源代码, 更为直接地体现了程序的行为逻辑。逆向分析分为静态和动态两类:静态分析的特点是不实际执行程序;反之, 通过在真实或模拟环境中执行程序进行分析的方法称为动态分析, 它们一般都要求测试人员对目标平台架构和汇编语言有精确的理解。IDA Pro[2]是目前功能最强的反汇编及调试工具, 能处理多种硬件平台下的原生代码, 包括使用Symbian C++SDK和iOS Objective-C开发的程序。开源工具smali[3]实现了在Android系统的dex格式文件及其反汇编代码之间的双向转换。
本文通过笔者在工作中的实际案例对手机软件二进制代码静态逆向安全测试的思路、方法、过程以及注意事项进行了介绍。测试对象是Symbian S60平台上某款免费下载软件中的两个主要可执行文件, 即主程序文件和下载加速器文件。
测试内容包括:
1. 该软件是否存在静默安装卸载其它软件的可能;
2. 是否存在未经用户授权而发送短信的嫌疑;
3.是否存在与其它软件产生恶意冲突的隐患;
4.是否存在泄漏用户隐私信息的风险。
1静默安装卸载
容易验证, 作为分析对象的两个可执行文件是使用诺基亚Symbian S60 C++SDK开发的, 运行在加载ARM芯片和S60 v3系统的手机上。如果它们调用了静默安装或卸载程序的功能, 则必然会引用相应的系统函数。因此, 这里的主要工作就是在目标文件的反汇编结果中分析对这些系统函数的调用情况。不过, C++编译器会对程序符号名称进行混淆 (Mangling) [4]以支持函数重载等语言特性, 所以还需要知道这些系统函数在二进制代码中对应的引用名。通过Google得知静默安装卸载功能位于S60SDK API插件的SW Installer Launcher部分[5], 进而从SDK中提取出对应的导入库文件swinstcli.lib。至此, 可以利用objdump工具[6]获得实际函数名与二进制代码引用名的对应关系:
(输出结果约440行, 从略) 。再参照SDK文档, 就可总结出S60 v3系统中静默安装卸载程序功能对应的系统服务函数名称, 如表1所示。
使用IDA Pro分别对两个可执行文件进行反汇编, 并搜索导入函数列表。主程序文件仅引用了有提示的程序卸载系统服务函数 (未在表1列出) , 不存在静默安装卸载程序的功能。但在下载加速器插件的反汇编代码中, 地址0x217D8至0x217F4之间出现了对SWInstCli_4和SWInstCli_13函数的连续调用, 如图1所示。对跳转地址回溯归并后发现, 共有4个静默安装卸载系统服务函数被程序自身实现的入口地址为0x216FC的函数调用, 它们构成一个完整的静默安装程序的过程。使用相同的方法, 还在同一可执行文件中查找到完整的静默卸载程序的过程。
被测软件的官方文档并未说明下载加速器插件模块为何需要使用静默安装卸载程序的功能, 因此对用户存在暗箱操作的可能。即使该功能仅用于软件自身的配置升级, 也应当提示用户有选择地进行操作, 而非静默执行。
以上描述了手工执行二进制代码静态逆向分析的方法, 整个过程较为繁琐。尤其是可执行文件中的函数调用关系错综复杂, 仅仅300余KB的下载加速器插件的函数逻辑图就达到了肉眼难以辨识的程度 (见图2) 。我们还利用IDA Pro提供的脚本扩展IDAPython[7]开发了一键式扫描工具, 只需要指定待测的二进制代码模块, 就能够全自动地分析模块自身实现的哪些函数调用了静默安装卸载功能, 并生成直观的调用关系图 (见图3) 。这种方法具有很强的普适性:测试人员按照一定的语法规范编写希望搜索的恶意代码行为模式, 就可以快速自动定位被测二进制代码中的调用地址, 获得准确的上下文逻辑结构。作为验证, 我们对被测软件包含的其它可执行文件和动态链接库文件进行过批量扫描, 准确查出了所有对于静默安装卸载功能的引用。
2未经授权发送短信
诺基亚S60 v3及以上的手机操作系统支持至少三种发送短信的方式:
1.“低级别”的使用网络套接字的SMS PDU (短信协议数据单元) 方式。首先创建一个短信对象CSmsMessage并设置短信内容, 然后调用SetToFromAddressL函数设定接收端的手机号码, 最后写入一个短信套接字RSmsSocketWriteS-tream并调用CommitL方法完成发送。
2.“较高级别”的RSendAs方式。
首先调用Connect方法连接到系统的发送短信服务, 调用CreateL方法创建一个短信对象, 然后调用AddRecipientL方法设定接收端的手机号码, 调用SetBodyTextL方法设置短信内容, 最后调用SendMessageAndCloseL完成发送。
3.“更高级别”的SendUI方式。
首先调用NewLC方法创建一个CMessageData对象, 然后调用CSendUi类的CreateAndSendMessageL方法弹出短信编辑界面, 就可以等待用户输入内容并完成发送。
值得注意, 前两种方式都不需要通过任何图形化界面与用户进行交互, 即所谓的“后台”发送。
使用与上一节类似的方法对主程序文件进行逆向分析, 发现它分别在地址0x7BB14和0x296C0处引用了第一和第三种发送短信的系统函数。在被测软件的界面上, 我们仅发现了一处明显需要使用发送短信功能的可操作项, 即菜单“选项→推荐给好友→短信推荐”。手工选择该菜单项后, 弹出了短信编辑框界面, 即对应于方式三。方式一的可操作项未出现在用户界面上, 因此存在未经用户授权发送短信的嫌疑。
通过类似的分析发现, 加速器插件调用了其它类型的API函数, 包括CSmsSettings::GetServiceCenter (获取服务中心对象) 、CSmsPDU::SetServiceCenterAddressL (设置服务中心地址) 、CSmsPDU::ToFromAddress (获取短信目的地址) 等。这些函数的功能是读取和设置短信服务的一些参数, 并不能发送短信。但是, 通常概念的下载加速器并不需要使用这些功能, 用户帮助文档上也未发现相关的声明。因此, 被测软件存在侵犯用户隐私的隐患。
3软件恶意冲突
软件恶意冲突的表现形式有很多种, 我们在测试时仅分析了强制终止其它进程的行为。在Symbian系统上, 根据指定的进程名 (允许包含通配符) 强制终止进程的常见步骤如下:
1.使用指定的进程名创建一个TFindHandleBase“句柄查找对象”;
2.调用TFindProcess::Next方法查找下一个匹配的进程名;
3. 若查找失败则结束, 否则调用RProcess:
:Open方法打开该进程, 获得对它的访问权限;
4. 调用RProcess::Kill方法强制终止该进程;
5. 如有必要, 返回第2步重复查找。
这刚好可以作为前面提出的“恶意代码行为模式”使用。利用脚本程序处理后发现, 两个可执行文件都包含与上述步骤几乎完全一致的代码逻辑。图4显示了下载加速器模块中对RProcess::Open和RProcess::Kill的调用情况。因此, 被测软件存在与其它软件产生恶意冲突的隐患。
4用户隐私泄漏
作为下载工具, 被测软件需要访问移动互联网是合情合理的, 因而从网络通信内容的角度进行分析比较困难。我们的思路是, 从软件内置的网址字符串入手, 发现可能存在的用户信息泄漏。
在主程序文件的反汇编代码中搜索字节长度不小于5的文本字符串 (包括ASCII和Unicode字符串) , 共得到755个匹配项。在结果中查找网址字符串 (包含字段“http://”、“www.”、“.com”、“.cn”、“.net”、“.org”、“.htm”、“.php”、“.asp”、“.aspx”等) , 发现地址0x5F950处内容为http://heimutuzhu.gotoip4.com/counter.php。在我们的测试期间, http://heimutuzhu.gotoip4.com/counter.php网页界面如图5所示, 通过观察判断它的功能可能为统计移动互联网流量。
在反汇编代码中对该字符串进行交叉引用查找, 只有1处使用了该网址字符串, 如图6所示。
这部分代码的功能是, 将上述网址字符串和另外两个字符串“?cid=XXX”、“&ver=YYY” (其中“XXX”和“YYY”由程序运行时生成) 拼接起来得到一个形如http://heimutuzhu.gotoip4.com/counter.php?cid=XXX&ver=YYY的“网页地址+参数信息”的URL链接。从上下文分析, “XXX”可能为用户或手机相关的ID号, “YYY”可能为手机机型、系统版本或其它版本参数。如果被测软件未经提示访问了上述URL链接, 就存在泄漏用户隐私的风险。
两个被测文件中还包含其它可疑网址字符串, 这里不继续展开分析。
5关于动态逆向分析
以上演示了通过手工和自动化方式对Symbian系统二进制代码进行静态逆向分析的过程, 二者都可以有机结合到上文提出的综合测试服务平台中。一般而言, 使用动态逆向分析有可能获得更为丰富的结果, 比如可以设置断点直接查看上一节中的具体版本参数值。IDA Pro确实提供了调试Symbian程序的能力[8], 但在本案例中效果并不理想, 原因之一是, 类似的联网软件很容易接受官方服务器指令改变自身行为逻辑, 而服务器端应用及数据在我们的测试中都没有条件获得, 因此很难重现某些恶意行为。虽然工作量较大, 静态逆向分析在这种情况下展现了独特的优势:二进制代码直接反映了源代码逻辑, 再加上软件包附带的数字签名的抗抵赖性, 就构成无法撤销的铁证。
6结语
自动化能力的提升是软件测试领域的发展方向, 能够发现并解决开发过程中无能为力的问题是专业测试的价值体现。手机软件安全测试的研究方兴未艾, 本文使用的逆向分析技术及案例分析是该领域的一个有益参考。
参考文献
[1]Brian Chess and Jacob West, Secure Programming with Static Analysis, Addison Wesley, 2007.
[2]IDA Pro, 交互式二进制代码逆向分析工具, http://www.hex-rays.com.
[3]smali-an assembler/disassembler for Android’s dex format, code.google.com/p/smali.
[4]Wikipedia, Name mangling, en.wikipedia.org/wiki/Name_mangling.
[5]Nokia Developer Website, Symbian S60Deploy-ment Installation-SW Installer Launcher API, www.developer.nokia.com/Community/Wiki/SW_Installer_Launcher_API.
[6]objdump, MinGW编译器套件中的库文件和目标文件符号转储工具 (开源) , nuwen.net/mingw.html.
[7]IDAPython, IDA Pro的Python脚本扩展, code.google.com/p/idapython.
代码测试 篇5
随着客户对软件质量要求的不断提高, 软件测试技术与测试方法的研究受到了越来越多的关注。测试可以划分为静态测试和动态测试两部分, 包括文档和代码的审查、测试用例的设计和运行、错误报告的生成等。从过程上划分, 软件测试一般包括单元测试、集成测试、系统测试和验收测试阶段。测试也可以划分为功能性测试和结构性测试。功能性测试使用规格说明, 结构性测试依靠程序[1]。在软件测试工作中, 代码覆盖测试是测试的底线, 特别是在嵌入式软件的测试中显得更为重要, 代码覆盖技术明显提高了软件的可靠性, 保证了软件的质量。
1 DD-路径与程序复杂度
决策到决策路径 (DD-路径) , 也称为路径链, 链是起始节点和终止节点不同的路径, DD-路径是DD-路径图中的一条链[1], DD-路径可分为下列5种:
(1) 情况1:由一个节点组成, 内度=0, 内度是该节点作为终止节点的不同边的条数。
(2) 情况2:由一个节点组成, 外度=0, 外度是该节点作为开始节点的不同边的条数。
(3) 情况3:由一个节点组成, 内度>=2, 或外度>=2。
(4) 情况4:由一个节点组成, 内度=1并且外度=1。
(5) 情况5:长度>=1的最大链。
程序从一个入口或一个判断点开始, 直到一个模块的出口或者判断结束, 构成了一条DD-路径。例如, 在一个典型的IF-THEN-ELSE-ENDIF结构中, 有两条路径, 通常称为THEN路径和ELSE路径。数学和图论表明, 一个结构化程序与平面的图是等价的, 而非结构化程序的图是非平面的。测试人员对软件的逻辑复杂性关注了很长的时间, 1989年, Tomas McCabe and Charles Butler基于DD-路径定义了程序复杂度V (G) 来研究软件逻辑复杂性, 它是程序逻辑复杂度的一个测量指标[2], 其计算方法有下列三种方式。
(1) 计算一个结构化程序的平面流程图的区域个数;
(2) V (G) =e-n+2, 其中e为流程图中边的条数, n是节点数;
(3) 构造程序图的强连通图, 计算公式修改为:V (G) =e-n+1。强连通图是3-连接的有向图, 即图中的任意两个节点之间有一条路径, 对于单入口单出口的结构, 最简单的做法是从出口节点到入口节点增加一有向边, 构造3-连接有向图。
图1是DD-路径分析程序复杂度, 该图将平面划分为5个区域, 标号为1到5, 若使用方法1计算循环复杂度, 由于平面的区域划分为5个, 因此V (G) =5;若使用方法2计算复杂度, V (G) =12-9+2=5;若使用方法3计算复杂度, 先构造强连通图, 从最后的节点到开始节点添加一条有向边, 这样, 边的数量增加为13, 复杂度V (G) =13-9+1=5。
对一个测试程序来说, 程序复杂性与基路径之间存在内在的联系, 基路径可以用来研究程序的复杂性。V (G) 是为实现完全覆盖所需要的最少独立路径数, V (G) 越大, 基路径就越多, 程序越复杂。因此, 我们设计程序时, 应追求尽可能小的程序基路径数, 以降低程序复杂度。
2 基路径覆盖测试技术
DD-路径能够非常精确地描述测试覆盖。表1列出的指标是被广泛接受的结构性测试指标, 指标主要来自E.F.Miller的研究工作。基路径测试给出了必须进行的测试下限。其中, C1指标是覆盖测试最低可接受级别[1,3], 它实现了DD-路径覆盖, C1P实现了判断的所有分支覆盖。在RTCA/DO-178B规定的适航软件的LEVEL B级别就要求软件达到C1P指标。
在工程项目的实施中, 结构性测试覆盖指标有两种使用方式:
(1) 作为一种强制执行的标准。例如, 所有单元都要达到DD-路径覆盖, 即指标C1。
(2) 或作为一种机制, 有选择性进行测试。例如, 对具有复杂逻辑的模块选择多条件覆盖, 对大量迭代处理的模块, 采用循环覆盖指标来测试。
下面通过一个例子, 来分析基于DD-路径的覆盖测试。在图2中, 基路径有6条, 分别是P1、P2、P3、P4、P5和P6。
其中:
(1) P1:A-B-C-F-G
(2) P2:A-B-D-F-G
(3) P3:A-B-E-F-G
(4) P4:A-B-E-D-F-G
(5) P5:A-B-C-D-F-G
(6) P6:A-B-D-F-G-B-D-F-G
为了实现C0覆盖指标, 测试必须覆盖所有语句, 因此测试的基路径有{P1, P2, P3}或{P1, P4}或{P3, P5}。为了实现C1覆盖指标, 测试必须覆盖所有DD-路径, 测试的基路径有{P1, P2, P3, P4, P5}。为了实现C2覆盖指标, 应实现C1+循环覆盖, 测试的基路径有{P1, P2, P3, P4, P5, P6}。
3 代码覆盖测试技术TRACE
TRACE技术是在嵌入式软件设计时, 在顺序、选择和循环三种基本代码结构中, 增加冗余设计TRACE, 利用TRACE可以检测软件执行过程中代码的覆盖程度, 检查应用软件所能达到的覆盖级别。设计人员在任何时候输入相应数据, 并从设备对应的地址单元中取到TRACE数据, 分析软件的执行情况, 如果取到的TRACE数据与软件运行的结构相吻合, 则程序正确, 如果取不到TRACE数据或数据相反, 则程序运行错误[4]。
TRACE的具体设计方法是:对于顺序语句代码, 在代码段结尾增加TRACE语句;对于循环语句代码, 在循环体的结尾加入TRACE语句;对选择或CASE语句代码, 在所有分支中加入TRACE语句。这里应特别强调的是不管条件的真和假有无代码, 在真假两个分支中都应加入TRACE语句。TRACE语句有2个参数, 一个是模块名, 一个是顺序号, 例如TRACE (A, i) , 表示A模块中的第i个覆盖点, 例如, 条件分支的TRACE覆盖采用如下设计。
4 TRACE技术在MODE-S应答机中的应用
4.1 MODE-S应答机
MODE-S应答机项目是中航总615研究所与Honeywell公司合作开发的数据链4级S模式空中交通空管设备, 属于飞行器通讯网ATN设备之一 (论文第一作者是原中航总上海615所软件工程师, 全程参与了该项目的研制工作) , 该设备在各国民用飞机已经装机2000多套。应答机采用双天线, 与高度源、TCAS、控制器、空中数据链处理器等设备连接, 数据连接总线是ARINC-429和ARINC-575, 另有部分离散量和模拟量数据接口, 应答机提供Air Data Loader/Portable Data Loader接口与地面测试设备连接。图3是应答机与其他空管设备的连接结构图[5]。
S模式应答机用于飞机与地面二次雷达的数据及时交换与通信, 飞机与其他飞机的TCAS II设备的通信, 保证TCAS II设备的空中防撞系统的功能, 实施空中交通管制。S模式应答机主要应答有:应答地面二次雷达的定向MODE-S询问, 询问格式有UF4、UF5、UF20和UF21, 应答格式DF4、DF5、DF20和DF21;广播询问UF11, 应答格式DF11;ATCRBS询问, A/C模式应答飞行代码和飞行高度;应答空中TCAS II设备的监视询问, 询问格式UF0和UF16, 应答格式DF0和DF16。
MODE-S应答机采用了指令级并行处理的Intel80960处理器, 软件使用C语言和汇编语言编写。软件分为启动软件和操作软件两部分。其中, 启动软件Boot Software是设备出厂时已经固化了的软件, 主要完成设备上电后系统的启动和操作软件的外场升级, 启动软件执行后应答机软件自动转入操作软件;操作软件Operation Software是设备工作时的功能性软件, 完成应答机的UF/DF和ATCRBS应答等功能, 通过RS-232接口可以升级操作软件。
在软件设计中使用了CRC技术来提高软件运行的可靠性, 生成设备的操作软件时, 使用CRC技术生成一个32位的Checksum数据, 每当操作软件使用PC加载到设备时, Checksum数据随应用程序一起加载到设备中。当设备开机运行时, 加电自检 (POST) , 启动软件使用CRC技术重新计算操作软件的Checksum数据, 在设备正常运行过程中, 操作软件将定时使用监控程序计算Checksum数据, 系统根据计算出的CRC值与原生成的CRC值比较, 检测程序的正确性。系统应用了监控技术和容错设计, 周期性地监控软件的运行过程, 以正确地发现故障并提高系统的可靠性。系统考虑了数据传输交换时瞬间出错情况, 系统能屏蔽此类错误, 通过错误监控程序, 在程序中增加容错资源程序, 定时检测程序相应的数据和参数[6]。
4.2 TRACE技术的应用
在MODE-S应答机项目中, 为了达到适航软件标准RTCA/DO-178B的级别LEVEL-B要求[7], 软件设计与测试采用了TRACE技术。
(1) TRACE的定义
设计时, 我们在trace.h文件中完成TRACE的定义。
(2) 初始化
TRACE的初始化工作在trace.c和global.c两个文件中完成。
trace* const trace_pointer = &trace_tags;
trace trace_tag2;
(3) TRACE应用
为达到适航软件满足RTCA/DO-178B的级别B的要求, 应用TRACE技术实施DD-路径覆盖。TRACE语句有2个参数, 一个是模块名, 一个是顺序号;例如TRACE (A, i) , 表示A模块中的第i个覆盖点。在定义TRACE时, 每个模块的TRACE分配了连续的地址空间, 每个TRACE顺序号对应了相应模块地址空间的一位 (1 bit) 。测试结果的分析只需要检查对应的地址空间的值。
在MODE-S应答机操作软件的高度处理模块中, 处理arinc_575高度的程序片段如下, 其中TRACE的第一个参数标明了高度模块, 第二个参数是arinc_575高度处理代码的选择分支顺序号。
5 结束语
DD-路径可以用于结构覆盖测试和程序复杂度分析, 覆盖测试是软件测试的底线, 代码覆盖技术的执行能保证应用软件达到相应的级别, Mode-S应答机项目中所采用的TRACE技术是基于DD-路径的代码覆盖测试技术, 在Honeywell公司与中航总615所的应答机合作项目中应用TRACE技术, 软件可靠性得到了保证, TRACE技术保证了应答机软件达到了RTCA适航软件Level B的要求。
摘要:代码覆盖测试技术可用于结构覆盖测试和程序复杂度分析, 代码覆盖测试技术可用于测试用例设计, 提高软件测试效率, 指导编写高质量的程序代码, 代码覆盖是软件测试的底线。代码覆盖测试技术及方法的研究, 为软件覆盖测试提供了理论依据。在Mode-S应答机项目中应用TRACE覆盖测试技术, 确保了产品满足适航软件标准RTCA/DO-178BLEVELB的要求。
关键词:代码覆盖,测试技术,DD-路径,Mode-S应答机,程序复杂度
参考文献
[1]Paul C Jorgensen.Software Testing:ACraftsman’s Approach[M].Sec-ond edition.CRC Press, 2002.
[2]Robert Culbertson, Chris Brown, Gary Cobb.RAPID TESTING[M].post&telecom press, 2002.
[3]柳纯录, 黄子河, 陈渌萍.软件评测师教程[M].清华大学出版社, 2005.
[4]Bart Broekman, Edwin Notenboom.嵌入式软件测试[M].张君施, 译.电子工业出版社, 2004.
[5]浦云明.软件设计引入容错技术及应用, 计算机应用与软件[J].2003, 20 (5) :60-62.
[6]赵会群.通信软件测试技术基础[M].人民邮电出版社, 2004.