源代码中内存错误的自动检测和定位方法技术

技术编号:15799094 阅读:182 留言:0更新日期:2017-07-11 13:15
本发明专利技术提供了源代码中内存错误的自动检测和定位方法,首先使用编译器对源代码进行词法分析和语法分析,构造符号表和抽象语法树;然后通过遍历抽象语法树,对可能产生内存错误的节点进行源代码变换,最后编译执行变换后的源代码,程序会自动判断内存错误的发生,并准确报告错误对应的源代码位置。本发明专利技术可以准确地自动检测和定位内存错误,实现更全面的错误检测,更好的兼容性,更好的平台普适性,更准确的源代码定位,更高的运行时性能和效率,从而提高软件的质量和软件维护的效率。

Automatic detection and location method of memory error in source code

The present invention provides a method of automatic detection and location of memory errors in the source code, the compiler first used for lexical analysis and syntax analysis of source code, structure symbol table and abstract syntax tree; and then by traversing the abstract syntax tree for possible node memory errors in source code transformation, finally compiled the transformed source the code, the program will automatically determine memory errors, and accurately report the error source code corresponding to the position. The invention can accurately detect and locate the automatic memory error, error detection to achieve a more comprehensive, better compatibility, better platform universal source code, more accurate positioning, higher operation performance and efficiency, thereby improving the quality of software and software maintenance efficiency.

【技术实现步骤摘要】
源代码中内存错误的自动检测和定位方法
本专利技术涉及一种源代码中内存错误的自动检测和定位方法,属于计算机软件领域,特别是指计算机软件测试领域。
技术介绍
内存错误是一种普遍存在于C/C++程序中的设计缺陷,可能导致软件运行异常和安全漏洞。内存错误包括空间内存错误、时间内存错误、类型内存错误。空间内存错误也称为缓冲区溢出错误,包括:数组越界、指针访问越界、指针使用前未初始化、空指针解引用、对任意整型数据进行强制类型转化得到的指针进行解引用等;时间内存错误包括:悬挂栈指针,悬挂堆指针、多次释放、不完全释放等;类型内存错误包括:释放非堆上的内存空间、将函数指针作为数据指针进行解引用、将数据指针作为函数指针进行函数调用等。这些错误可能导致软件运行异常或崩溃,也可能被黑客利用来执行恶意代码,从而导致安全漏洞。对于安全关键软件和系统,这将会导致严重后果和巨大损失。因此,实现内存错误的高效自动检测和源代码定位,能够帮助开发人员在软件开发过程中发现并改正这些错误,极大地提高软件的质量和软件维护的效率。目前常见的检测技术主要是扩展指针技术,该技术是通过扩展指针的数据类型,使指针在原来只存储一个内存地址的基础上,再额外记录该指针所指向内存块的基地址和大小等信息,以便在指针解引用时可以判断该指针是否在其所指向内存块的有效区间内,从而判断指针解引用是否存在错误。由于该技术修改了代码中指针的存储结构,造成了处理后的代码与原代码之间的不兼容,导致检测结果不稳定。此外,由于该技术只对指针所指向内存块的边界信息进行了记录,所以只能处理空间内存错误,无法检测时间和类型内存错误。目前常见的检测技术主要针对二进制代码,即通过对程序的二进制代码进行修改,然后运行修改后的二进制代码以检测内存错误。由于该技术是对二进制代码进行修改,所以不具备平台普适性,即修改工具只能处理主流平台的二进制代码,而无法兼容某些领域所使用的特定的运行平台。此外,由于该技术无法准确定位到错误对应的源代码位置,导致不容易对错误进行调试。因此,有必要提供一种新的内存错误的自动检测和源代码定位方法,以实现更全面的错误检测,更好的兼容性,更好的平台普适性,更准确的源代码定位,更高的运行时性能和效率,从而克服现有检测技术中存在的问题。
技术实现思路
为了克服上述已有技术和方法存在的不足,本专利技术的目的旨在提供一种源代码中内存错误的自动检测和定位方法,该方法通过使用源代码变换技术,将源代码变换为带有自动检测和错误定位功能的源代码,包括对指针定义初始化和赋值节点插入代码来记录或更新指针元数据,对指针解引用和数组下标访问节点插入内存错误检测和源代码定位的机制,对函数定义节点插入代码来更新形参的指针元数据,并插入包装函数定义来在函数之间传递指针元数据,对函数调用节点插入额外的实参来传入原实参的指针元数据;使得可以在软件运行过程中自动检测和定位软件中的内存访问错误,以实现更全面的错误检测,更好的兼容性,更好的平台普适性,更准确的源代码定位,更高的运行时性能和效率,从而克服现有的检测技术中存在的问题。技术方案:源代码中内存错误的自动检测和定位方法,包括:步骤1、使用编译器对源代码进行词法分析和语法分析,构造包含节点类型信息的符号表以及抽象语法树;步骤2、遍历抽象语法树,对指针变量定义初始化节点和赋值节点插入代码来记录或更新指针元数据,其中指针元数据包括指针指向内存块的边界、状态和类型信息;步骤3、遍历抽象语法树,对指针解引用节点和数组下标访问节点插入内存错误检测和源代码定位的机制;步骤4、遍历抽象语法树,对函数定义节点插入代码来更新形参的指针元数据,并插入包装函数定义来在函数之间传递指针元数据;步骤5、遍历抽象语法树,对函数调用节点插入额外的实参来传入原实参的指针元数据;步骤6、编译执行变换后的源代码,程序会自动判断内存错误的发生,并准确报告错误对应的源代码位置。具体步骤包括:步骤S1,选择需要变换的源代码目录,或者单个源代码文件;步骤S2,将选择的源代码目录或文件复制到源代码变换的工作目录中;步骤S3,对工作目录中的所有源文件进行宏扩展处理,并保存扩展结果到相应的源文件中;进一步地,宏扩展处理具体包括:操作1、利用编译器的词法分析器对文件进行词法分析,词法分析器返回经过宏扩展处理之后的词法单元;操作2、针对扩展自宏的词法单元,其属性中包括宏扩展之后的内容和宏扩展的位置,用扩展之后的内容替换宏扩展位置的原有内容;步骤S4,遍历工作目录中的所有源文件,使用编译器对源代码进行词法分析和语法分析,构造符号表和抽象语法树;所述符号表中包含节点的类型信息;步骤S5,遍历抽象语法树,若当前节点是变量定义初始化表达式,则判断该变量是否为指针类型或者是包含指针成员的结构体类型,若是则插入代码来记录指针元数据,若不是则转至步骤S6;步骤S6,遍历抽象语法树,若当前节点是变量赋值表达式,则判断该表达式是否为指针赋值或者是包含指针成员的结构体赋值,若是则插入代码来更新指针元数据,若不是则转至步骤S7;步骤S7,遍历抽象语法树,若当前节点是指针解引用表达式或者数组下标访问表达式,则插入内存错误检测和源代码定位的机制,否则转至步骤S8;步骤S8,遍历抽象语法树,若当前节点是函数定义,假设函数名为func8,返回值类型为RetType,则判断该函数的返回值和形参是否为指针类型或者是包含指针成员的结构体类型,若是则插入代码来更新形参的指针元数据,并插入包装函数定义来在函数之间传递指针元数据,若不是则转至步骤S9;步骤S9,遍历抽象语法树,若当前节点是函数调用表达式func9(a1,an),其中func9是函数名,a1,an表示n个实参,则判断该函数的返回值和形参是否为指针类型或者是包含指针成员的结构体类型,若是则插入额外的实参来传入原实参的指针元数据,若不是则转至步骤S10;步骤S10,对于所有被改写的源文件,在文件开始位置插入include语句,用于包含所有数据结构、指针元数据操作函数和检测函数的定义文件;步骤S11,将步骤S5到步骤S10中的所有替换改写保存到相应的源文件中,并将本次改写的文件加入已处理文件列表;步骤S12,将经过变换的源代码目录或源代码文件按原有方式进行编译,生成可执行文件;步骤S13,将可执行文件部署在目标平台上并运行,当出现内存错误时,插入的代码可以自动检测到错误的发生,并准确定位和报告错误在源代码中的位置;其中步骤S5~S9的操作可以合并为遍历抽象语法树过程中的一个步骤或者同时执行。所述步骤S5中插入代码来记录指针元数据,进一步包括:步骤S51,若当前节点是指针变量定义Type51p51=Expr51(kpe51),其中Type51是指针变量类型,p51是指针变量名,kpe51是初始化表达式中的核心指针,Expr51(kpe51)是由kpe51构成的初始化表达式;步骤S5101,若该核心指针kpe51是指针变量pv51,则将该变量定义替换为:Type51p51=Expr51((Type51)PRFpmd_tbl_update_ptr_ret(&p51,&pv51,pv51))其中函数PRFpmd_tbl_update_ptr_ret用于将p51的指针元数据更新为pv51的本文档来自技高网
...
源代码中内存错误的自动检测和定位方法

【技术保护点】
源代码中内存错误的自动检测和定位方法,其特征在于,包括:步骤1、使用编译器对源代码进行词法分析和语法分析,构造包含节点类型信息的符号表以及抽象语法树;步骤2、遍历抽象语法树,对指针变量定义初始化节点和赋值节点插入代码来记录或更新指针元数据,其中指针元数据包括指针指向内存块的边界、状态和类型信息;步骤3、遍历抽象语法树,对指针解引用节点和数组下标访问节点插入内存错误检测和源代码定位的机制;步骤4、遍历抽象语法树,对函数定义节点插入代码来更新形参的指针元数据,并插入包装函数定义来在函数之间传递指针元数据;步骤5、遍历抽象语法树,对函数调用节点插入额外的实参来传入原实参的指针元数据;步骤6、编译执行变换后的源代码,程序会自动判断内存错误的发生,并准确报告错误对应的源代码位置。

【技术特征摘要】
1.源代码中内存错误的自动检测和定位方法,其特征在于,包括:步骤1、使用编译器对源代码进行词法分析和语法分析,构造包含节点类型信息的符号表以及抽象语法树;步骤2、遍历抽象语法树,对指针变量定义初始化节点和赋值节点插入代码来记录或更新指针元数据,其中指针元数据包括指针指向内存块的边界、状态和类型信息;步骤3、遍历抽象语法树,对指针解引用节点和数组下标访问节点插入内存错误检测和源代码定位的机制;步骤4、遍历抽象语法树,对函数定义节点插入代码来更新形参的指针元数据,并插入包装函数定义来在函数之间传递指针元数据;步骤5、遍历抽象语法树,对函数调用节点插入额外的实参来传入原实参的指针元数据;步骤6、编译执行变换后的源代码,程序会自动判断内存错误的发生,并准确报告错误对应的源代码位置。2.如权利要求1所述的源代码中内存错误的自动检测和定位方法,其特征在于,具体步骤包括:步骤S1,选择需要变换的源代码目录,或者单个源代码文件;步骤S2,将选择的源代码目录或文件复制到源代码变换的工作目录中;步骤S3,对工作目录中的所有源文件进行宏扩展处理,并保存扩展结果到相应的源文件中;进一步地,宏扩展处理具体包括:操作1、利用编译器的词法分析器对文件进行词法分析,词法分析器返回经过宏扩展处理之后的词法单元;操作2、针对扩展自宏的词法单元,其属性中包括宏扩展之后的内容和宏扩展的位置,用扩展之后的内容替换宏扩展位置的原有内容;步骤S4,遍历工作目录中的所有源文件,使用编译器对源代码进行词法分析和语法分析,构造符号表和抽象语法树;所述符号表中包含节点的类型信息;步骤S5,遍历抽象语法树,若当前节点是变量定义初始化表达式,则判断该变量是否为指针类型或者是包含指针成员的结构体类型,若是则插入代码来记录指针元数据,若不是则转至步骤S6;步骤S6,遍历抽象语法树,若当前节点是变量赋值表达式,则判断该表达式是否为指针赋值或者是包含指针成员的结构体赋值,若是则插入代码来更新指针元数据,若不是则转至步骤S7;步骤S7,遍历抽象语法树,若当前节点是指针解引用表达式或者数组下标访问表达式,则插入内存错误检测和源代码定位的机制,否则转至步骤S8;步骤S8,遍历抽象语法树,若当前节点是函数定义,假设函数名为func8,返回值类型为RetType,则判断该函数的返回值和形参是否为指针类型或者是包含指针成员的结构体类型,若是则插入代码来更新形参的指针元数据,并插入包装函数定义来在函数之间传递指针元数据,若不是则转至步骤S9;步骤S9,遍历抽象语法树,若当前节点是函数调用表达式func9(a1,an),其中func9是函数名,a1,an表示n个实参,则判断该函数的返回值和形参是否为指针类型或者是包含指针成员的结构体类型,若是则插入额外的实参来传入原实参的指针元数据,若不是则转至步骤S10;步骤S10,对于所有被改写的源文件,在文件开始位置插入include语句,用于包含所有数据结构、指针元数据操作函数和检测函数的定义文件;步骤S11,将步骤S5到步骤S10中的所有替换改写保存到相应的源文件中,并将本次改写的文件加入已处理文件列表;步骤S12,将经过变换的源代码目录或源代码文件按原有方式进行编译,生成可执行文件;步骤S13,将可执行文件部署在目标平台上并运行,当出现内存错误时,插入的代码可以自动检测到错误的发生,并准确定位和报告错误在源代码中的位置;其中步骤S5~S9的操作可以合并为遍历抽象语法树过程中的一个步骤或者同时执行。3.如权利要求2所述的源代码中内存错误的自动检测和定位方法,其特征在于,所述步骤S5中插入代码来记录指针元数据,进一步包括:步骤S51,若当前节点是指针变量定义Type51p51=Expr51(kpe51),其中Type51是指针变量类型,p51是指针变量名,kpe51是初始化表达式中的核心指针,Expr51(kpe51)是由kpe51构成的初始化表达式;步骤S5101,若该核心指针kpe51是指针变量pv51,则将该变量定义替换为:Type51p51=Expr51((Type51)PRFpmd_tbl_update_ptr_ret(&p51,&pv51,pv51))其中函数PRFpmd_tbl_update_ptr_ret用于将p51的指针元数据更新为pv51的指针元数据;步骤S5102,若该核心指针kpe51是指针常量pc51,则将该变量定义替换为:Type51p51=Expr51((Type51)PRFpmd_tbl_update_as_ret(&p51,pc51_status,pc51_base,pc51_bound,pc51))其中函数PRFpmd_tbl_update_as_ret用于将p51的指针元数据更新为其余实参所表示的信息,pc51_status、pc51_base、pc51_bound分别是pc51的状态、下界和上界信息;步骤S5103,若该核心指针kpe51是函数调用func51(a1,an),其中函数func51返回一个指针,a1,an表示n个实参,则将该变量定义替换为:Type51p51=Expr51(PRFfunc51(&p51,a1,an))其中函数PRFfunc51是func51的包装函数,用于将p51的指针元数据更新为func51返回值的指针元数据;步骤S5104,若该核心指针kpe51是条件表达式cond?true_ptr:false_ptr,则将该变量定义替换为:Type51p51=Expr51((Type51)PRFcond_expr(&p51,PRFpmd_tbl_lookup(&true_ptr),PRFpmd_tbl_lookup(&false_ptr),cond,cond?true_ptr:false_ptr))其中函数PRFcond_expr用于将p51的指针元数据更新为条件表达式返回值的指针元数据;步骤S52,若当前节点是结构体变量定义structst52obj52=Expr52,其中st52是结构体变量类型,且包含n个指针成员(用pf1,pfn表示),obj52是结构体变量名,Expr52是初始化表达式;步骤S5201,若该初始化表达式Expr52是结构体变量表达式Expr52(kpe52),其中kpe52是初始化表达式中的核心结构体,Expr52(kpe52)是由kpe52构成的初始化表达式,则将该变量定义替换为:structst52obj52=(PRFpmd_tbl_update_ptr(&obj52.pf1,&kpe52.pf1),PRFpmd_tbl_update_ptr(&obj52.pfn,&kpe52.pfn),Expr52(kpe52));其中函数PRFpmd_tbl_update_ptr和逗号表达式用于将obj52中所有指针成员的指针元数据更新为kpe52中相应指针成员的指针元数据;步骤S5202,若该初始化表达式Expr52是基于函数调用的结构体变量表达式Expr52(func52(a1,an)),其中函数func52返回一个结构体,a1,an表示n个实参,则将该变量定义替换为:structst52obj52=Expr52(PRFfunc52(&obj52,a1,an))其中函数PRFfunc52是func52的包装函数,用于将obj52中所有指针成员的指针元数据更新为func52返回值中相应指针成员的指针元数据;步骤S5203,若该初始化表达式Expr52是初始值表达式列表{Expr521(kpe521),Expr52n(kpe52n)},其中Expr52i(kpe52i)是由核心指针kpe52i构成的初始值表达式,1≤i≤n,则将该变量定义替换为:structst52obj52={PRFpmd_tbl_update_ptr_ret(&obj52.pf1,&kpe521,Expr521(kpe521)),PRFpmd_tbl_update_ptr_ret(&obj52.pfn,&kpe52n,Expr52n(kpe52n))}其中函数PRFpmd_tbl_update_ptr_ret用于将obj52.pfi的指针元数据更新为kpe52i的指针元数据。4.如权利要求2所述的源代码中内存错误的自动检测和定位方法,其特征在于,所述步骤S6中插入代码来更新指针元数据,进一步包括:步骤S61,若当前节点是指针赋值Expr61A(p61)=Expr61B(kpe61),其中p61是赋值表达式左部中的核心指针变量,其类型是指针类型Type61,Expr61A(p61)是由p61构成的赋值表达式左部,kpe61是赋值表达式右部中的核心指针,Expr61B(kpe61)是由kpe61构成的赋值表达式右部;步骤S6101,若该赋值表达式右部中的核心指针kpe61是指针变量pv61,则将该赋值表达式替换为:Expr61A(p61)=Expr61B((Type61)PRFpmd_tbl_update_ptr_ret(&p61,&pv61,pv61))其中函数PRFpmd_tbl_update_ptr_ret用于将p61的指针元数据更新为pv61的指针元数据;步骤S6102,若该赋值表达式右部中的核心指针kpe61是指针常量pc61,则将该赋值表达式替换为:Expr61A(p61)=Expr61B((Type61)PRFpmd_tbl_update_as_ret(&p61,pc61_status,pc61_base,p61_bound,pc61))其中函数PRFpmd_tbl_update_as_ret用于将p61的指针元数据更新为其余实参所表示的信息,pc61_status、pc61_base、pc61_bound分别是pc61的状态、下界和上界信息;步骤S6103,若该赋值表达式右部中的核心指针kpe61是函数调用func61(a1,an),其中函数func61返回一个指针,a1,an表示n个实参,则将该赋值表达式替换为:Expr61A(p61)=Expr61B(PRFfunc61(&p61,a1,an))其中函数PRFfunc61是func61的包装函数,用于将p61的指针元数据更新为func61返回值的指针元数据;步骤S6104,若该赋值表达式右部中的核心指针kpe61是条件表达式cond?true_ptr:false_ptr,则将该赋值表达式替换为:Expr61A(p61)=Expr61B((Type61)PRFcond_expr(&p61,PRFpmd_tbl_lookup(&true_ptr),PRFpmd_tbl_lookup(&false_ptr),cond,cond?true_ptr:false_ptr))其中函数PRFcond_expr用于将p61的指针元数据更新为条件表达式返回值的指针元数据;步骤S62,若当前...

【专利技术属性】
技术研发人员:陈哲严俊琦杨志斌黄志球
申请(专利权)人:南京航空航天大学
类型:发明
国别省市:江苏,32

网友询问留言 已有0条评论
  • 还没有人留言评论。发表了对其他浏览者有用的留言会获得科技券。

1