C程序变量错误检测技术的设计与实现
2016-12-15杜世奇
杭 欢,杜世奇
(1. 北京邮电大学网络技术研究院,北京市 100876;2. 安徽师范大学数学计算机科学学院,安徽省芜湖市 241002)
C程序变量错误检测技术的设计与实现
杭 欢1,杜世奇2
(1. 北京邮电大学网络技术研究院,北京市 100876;2. 安徽师范大学数学计算机科学学院,安徽省芜湖市 241002)
C语言自其出现以来便以其优秀的特性被广泛应用于程序开发中,如今C语言程序在各大领域依然发挥着重要的作用,尤其在一些重要的部门领域如航空航天、医疗、银行等部门提供着系统支持,相应的在软件安全和系统稳定上有更高的要求。本文主要针对C语言程序中常见的变量异常检测进行研究,以现有开源软件位基础实现编译器前端对C语言源程序进行词法语法解析,并实现基于C语言源代码插桩检测程序变量使用异常的实验,对“变量使用前未赋初值”、“变量值溢出”等变量使用错误错误实现检测和反馈。
C语言;变量异常;代码插桩;编译器
本文著录格式:杭欢,杜世奇. C程序变量错误检测技术的设计与实现[J]. 软件,2016,37(11):84-87
0 引言
C语言诞生于1972年,以简洁和功能强大而著称于世,直到数十年后的今天仍被广泛使用,具有十分重要的地位。目前C语言的应用领域仍十分广阔,当对性能有较高要求时,常常会选择使用C语言实现,如Linux操作系统、Nginx服务器、GCC编译器等等。
1 课题研究的意义和需求
C语言的普及决定了其安全性和稳定性对社会生产至关重要,但是与Java等更加高级的编程语言相比,C语言提供的异常处理等机制比较简单,绝大部分情况下,程序员需要自己保证代码的正确性,而错误的代价常常是软件或系统崩溃。因此,C程序员们需要付出更多努力去编写C程序,而本文提供的技术可以帮助C语言使用者发现程序变量的使用错误,提高软件的安全性和稳定性。
2 相关概念和技术
2.1 代码插桩
插桩即是在被测程序中人为的插入一些探测性程序段,执行时获取程序的控制流和数据流信息。设计插桩方案时需要考虑到插桩位置、插桩策略和插桩时间等因素[1]。
以插桩时间为维度常见有基于源代码的插桩和机遇目标代码的插桩之分。
源代码插桩技术是在对程序源代码进行词法和
语法的分析后在需要检测的位置插入探针结构,之后随同编译过程中的源码一起构建克执行程序块并在测试期间执行检测,因此源代码插桩的准确度较高。然而由于编程语言种类繁多,进行源代码插桩对不同的语言要实现相对应的版本,工作量较大。
目标代码插桩是在目标代码生成之后再插入探针,探针程序的实现上只与系统底层或硬件相关而无需考虑源代码是何种语言实现的,解决了源代码插桩的弊端,但目标代码插桩也有其自身的弊端,因目标代码相对于源代码较难理解,不易处理,对目标代码的分析和插桩实现较为困难,准确度较低[2]。
2.2 Flex和Bison
Flex是一个词法分析器生成工具,通过读入一个有特定格式的输入文件来生成相应的分析器。该输入文件包含描述模式的正则表达式和对该模式进行处理的C代码,Flex对其解析之后生成解析函数,并输出到一个具有特定文件名的C代码源文件中,可包含或调用其中的代码以使用此分析器。
Bison是自由软件基金会GNU项目开发的一个语法分析器生成器,主要作用是将LALR(1)上下文无关文法的描述转化成分析该文法的C程序,兼容Yacc,并在其基础上做了一些改进。Bison经常和Flex一起使用,同样需要读入特定的输入文件来生成相应的语法分析器。
3 词法语法分析器的实现
对C语言程序变量的插装处理过程首先需要构建编译器前端,在对源代码进行完整的词法、语法分析的基础上,构造出程序的符号表和语法树等源码结构化数据,用于之后的探针代码的插入分析和处理。词法和语法分析器通过开源软件构造,下图展示了相关过程和工具:
图1 步骤及工具
我们分别以Flex和Bison工具为基础生成的相应的词法和语法分析逻辑对C语言程序惊醒此法和语法上的分析并产生对应的语法树结构数据,获取源代码的结构化语义信息,针对变量使用节点上进行节点插装来实现运行期变量检测。
3.1 文法语法分析器的生成
语法定义完成后,需要将输入文件转换为内部标记类型的Token并存储在内存中以备使用,使用Flex完成。
文法分析器使用Bison生成。
语句包括声明、表达式、选择、循环、复合语句和空语句,作为Bison输入文件实现产生类C语言文法的语法分析器的[3]。
3.2 设计AST(抽象语法树)
抽象语法树是程序的一种结构化形式,用树形结构来保存源代码的语法结构信息。
抽象语法树描述了源程序结构信息在内存中的表现形式,首先需要设计好语法树节点作为语法分析中的数据结构,为每个语义单元创建结构。函数的声明、调用,变量的声明、引用,这些都构成了抽象语法树的节点[4]。
抽象语法树节点设计如下图,如图2所示。
3.3 符号表结构设计
符号表是在编译前期有编译器前段对源代码进行分析的过程中保存的一种数据结构,用来存储源代码信息的表格的统称,包含常数表、变量名表、函数名表、标号表等[5]。源程序中的每个标识符都会在符号表中建立一个条目,并记录这个标识符的相应信息,如类型、内存地址和作用域等。
C语言是一种静态类型语言,即在使用标识符前,都需事先定义或声明。符号表中保存了当前状态下已存在的标识符,可以用来判断某个标识符是否未经定义或声明就使用。
4 C语言程序检测技术的实现
4.1 总体流程
对研究和设计部分的结果进行组装和细化,我们得到了下面流程设计图:
主要分为分析和检测两大部分,通过词法语法分析得到源代码的分析结果后对其中的变量使用情况进行检测。
4.2 检测流程
源代码经过词法和语法分析后就可以获得相应的抽象语义树,基于语义树信息对源程序进行分析和插桩操作。
具体过程是,遍历抽象语义树,获取树中的每个节点保存的语义信息,对于变量声明、变量引用和变量初始化或赋值等不同信息,采用不同的操作,
如新增变量信息、判断变量是否已声明、检测变量是否已初始化等,并输出相应结果。
流程如图4。
图2 节点结构定义
图3 分析流程图
4.3 检测实现
4.3.1 词法语法分析实现
在对源代码进行实际的分析和插装处理之前,需要对源程序进行一定的预处理,删除冗余的注释信息和用于代码格式化的字符,避免后期处理冗余处理这些无用自负字符,然后将处理后的程序代码转存到另一个文件。
预处理后的源程序经过词法分析,生成描述Token的Token列表文件,Token信息一方面用来进行下一步的语法分析,另一方面保存变量的相关信息,为后续的变量检测作准备;再经过语法分析,生成源程序对应的抽象语法树信息文件。自动地进行分析和插装处理插入探针程序用以以检测变量的使用情况,但是过多的探针程序会严重影响程序的性能,因此需要谨慎地设计探针程序的数量和插入位置[6]。
4.3.2 变量使用异常检测实现
完成了对源代码的分析之后,得到了对应于源代码的语法树,基于这棵语法树对程序中的变量声明、赋值和引用等进行检测。
变量未声明检测:C语言中变量和函数在使用前必须已定义或声明,根据符号表中标识符信息检测当前变量或函数名是否可用。
变量未初始化或未赋值检测:若变量已声明,则此变量可用,但未初始化和赋值的变量其值是随机的,访问此类变量可能造成系统崩溃,C语言本身对此没有强制规定,由程序员保证安全性。本文实现的技术对此类情况提供了检测。
变量值溢出检测:C语言的变量是有类型的,如int、float等,变量类型对应存储方式,如编码和长度,计算机在分配内存时严格按照变量声明的类型分配固定字节数的内存,因而变量的表示范围是有限的。若在不同类型的变量之间进行赋值,可能会出现溢出,即所赋值的变量大小超过被赋值变量所能表示的范围时,原始数据会被截断,被赋值变
量只能取得部分数据。此时,所取得的数据可能是无意义的,在某些情况下会导致严重后果。本文实现的技术能够对赋值进行检测,当所赋的值超过被赋值变量所能表示的范围时,进行相应的提示。
下图是对源代码运行本文实现的检测程序后的结果:
图4 检测流程图
图5 变量检测运行结果
程序对源代码进行词法语法分析后检测变量的使用,结果可以如预期对变量使用前未声明、变量未初始化错误和变量值溢出等情况进行提示,可以有效避免因变量使用错误产生的不必要的错误。
5 总结
本文基于开源软件设计并实现了C语言变量检测技术,能够对源代码中的变量使用异常进行检测并输出,提高了程序的健壮性,基本完成了预定设计需求,达到了预计设计目标;但由于时间和技术水平的不足,仍存在一定的缺陷。下一步工作是继续研究和完善相关技术,提供更丰富的检测功能,进一步提高其实用价值。
[1] 郭锐. 用于覆盖测试的代码插桩程序设计与实现[J]. 科学技术与工程, 2013, 13(30): 9072-9077.
[2] 蔡建平. 覆盖测试中高效代码插桩技术的研究[J]. 微计算机信息(嵌入式与SOC), 26(9-2): 86-88.
[3] 晏华. 代码自动插装技术的研究与实现[J]. 电子科技大学学报, 2002, 31(1): 62-66.
[4] 何群, 陈英. 面向对象语言编译器的自动测试平台[J]. 计算机工程, 2005, 31(14): 99-101.
[5] [美]弗雷泽著, 王挺等译. 可变目标C编译器: 设计与实现[M]. 电子工业出版社, 2005, 1.
[6] 刘慧梅. 软件测试中代码分析与插装技术研究[J]. 陕西国防工业职业技术学院学报, 2005, 24(2): 7-11.
Detection Technology about C Program Variable
HANG Huan1, DU Shi-qi2
(1. Institute of Network and Technology, Beijing University of Posts and Telecommunications, Beijing 100876, China; 2. Mathematics and Computer Science School, Anhui Normal University, Beijing 241002, China)
Since its inception, C has been widely used in the development of programs with its excellent features. Today, the C language program still plays an important role in various fields, especially in some important sectors such as aerospace, medical, banking, etc. Departments to provide system support. Therefore, higher security and stability are required in systems and softwares developed by C language. In this paper, we study the detection technology about mistakes in using C program variable. We implement a compiler front-end based on opensource software to do lexical and grammar analysis for C program variable. Then we experiment with it on instrumentation to monitor errors for noninitialized variables and variable overflow.
C programming language; Variable anomaly detection; Instrumentation; Compiler
TP312
A
10.3969/j.issn.1003-6970.2016.11.018
杭欢(1991-),男,硕士研究生,SDN 杜世奇(1992-),男,本科,编译原理。