[发明专利]数组越界错误的自动检测和校正方法有效
申请号: | 201410022323.0 | 申请日: | 2014-01-17 |
公开(公告)号: | CN103778061A | 公开(公告)日: | 2014-05-07 |
发明(设计)人: | 陈哲;李文明;黄志球 | 申请(专利权)人: | 南京航空航天大学 |
主分类号: | G06F11/36 | 分类号: | G06F11/36 |
代理公司: | 南京经纬专利商标代理有限公司 32200 | 代理人: | 朱小兵;刘谦 |
地址: | 210016 江*** | 国省代码: | 江苏;32 |
权利要求书: | 查看更多 | 说明书: | 查看更多 |
摘要: | |||
搜索关键词: | 数组 越界 错误 自动检测 校正 方法 | ||
1.一种数组越界错误的自动检测和校正方法,其特征在于,包括:
步骤1、选择待变换的源代码项目目录,或者单个源代码文件;
步骤2、针对待变换的源代码,利用编译器生成源代码的符号表和抽象语法树;
步骤3、遍历抽象语法树中的所有结点,构造指针依赖图,并进行源代码变换计算,其中:所述指针依赖图是一个有向图二元组,所述有向图二元组包括源代码中的指针集合和源代码中的指针依赖关系集合,所述源代码中的指针集合构成指针依赖图中的结点集合,所述源代码中的指针依赖关系集合构成指针依赖图中的有向边集合;
步骤4、根据步骤3的计算结果,在源代码中将需替换的部分源代码进行替换,生成变换后的源代码,并保存到新项目目录或新文件;
步骤5、定义数组越界检测策略和校正策略,并将这些策略转化为函数__MNT_CHK_AAV的定义,将按照策略生成的函数__MNT_CHK_AAV的定义写入变换后源代码的开头部分;
步骤6、将变换后的项目目录或文件用原编译器进行编译,生成目标系统上的可执行文件;
步骤7、将生成的可执行文件部署到目标系统并运行,当可执行文件运行到已替换或插入的代码段时,将自动检测和校正数组越界错误,并准确报告错误对应的源代码位置。
2.如权利要求1所述的数组越界错误的自动检测和校正方法,其特征在于,所述遍历抽象语法树中的所有结点,构造指针依赖图,并进行源代码变换计算,进一步包括:
在遍历抽象语法树的过程中,根据当前遍历到的结点s的类型进行如下操作之一:
向指针依赖图中加入指针依赖关系,
将数组下标访问表达式和指针访问表达式替换为__MNT_CHK_AAV函数的调用,
将函数声明、函数定义、函数调用表达式替换为新的表达式。
3.如权利要求1所述的数组越界错误的自动检测和校正方法,其特征在于,所述在遍历抽象语法树的过程中,根据当前遍历到的结点s的类型进行如下操作之一:向指针依赖图中加入指针依赖关系,将数组下标访问表达式和指针访问表达式替换为__MNT_CHK_AAV函数的调用,将函数声明、函数定义、函数调用表达式替换为新的表达式,进一步包括:
在遍历抽象语法树的过程中,对于当前遍历到的结点s,得到其所在的源文件名filename和代码行号loc,并根据当前遍历到的结点s的类型分别进行如下操作:
操作1、如果结点s是一个带初始值的指针声明type*p=expr,其中p为指针名,expr为表达式,且expr中包含一个支配指针q,则将指针对(p,q)作为一条边加入指针依赖图;
操作2、如果结点s是一个指针赋值表达式p=expr,其中p为指针名,expr为表达式,且expr中包含一个支配指针q,则将(p,q)作为一条边加入指针依赖图;
操作3、如果结点s是一个数组下标表达式p[expr],其中p为指针名或数组名,expr为表达式,则根据p的类型分别进行如下操作:
操作31、如果p是符号表中已定义的一个数组,则从符号表中获取该数组的类型type和长度len,然后将该表达式替换为如下函数调用:
*((type*)(__MNT_CHECK_AAV(p+expr,p,p+len,filename,loc)))
其中,函数参数p+expr表示数组下标表达式访问的内存地址,函数参数p表示数组的起始地址,函数参数p+len表示数组的结束地址,函数参数filename表示源文件名,函数参数loc表示代码行号;
操作32、如果p是所在函数声明的第n个形式参数,则从符号表中获取该指针的类型type,然后将该表达式替换为如下函数调用:
*((type*)(__MNT_CHK_AAV(p+expr,__MNT_CHK_AAV_B_n,__MNT_CHK_AAV_E_n,filename,loc)))
其中,函数参数p+expr表示数组下标表达式访问的内存地址,函数参数__MNT_CHK_AAV_B_n表示第n个形式参数的起始地址,函数参数__MNT_CHK_AAV_E_n表示第n个形式参数的结束地址,函数参数filename表示源文件名,函数参数loc表示代码行号;
操作33、如果p是不满足以上操作31、操作32中的两种情况的指针,则从指针依赖图中获取其最终依赖指针q,如果q不存在,则认为源代码中存在指针使用前未赋初值的错误,并报错,如果q存在,则根据q的类型分别进行如下操作:
操作331、如果q是符号表中已定义的一个数组,则从符号表中获取指针p的类型type和数组q的长度len,然后将该表达式替换为如下函数调用:
*((type*)(__MNT_CHECK_AAV(p+expr,q,q+len,filename,loc)))
其中,函数参数p+expr表示数组下标表达式访问的内存地址,函数参数q表示数组的起始地址,函数参数q+len表示数组的结束地址,函数参数filename表示源文件名,函数参数loc表示代码行号;
操作332、如果q是所在函数声明的第n个形式参数,则从符号表中获取指针p的类型type,然后将该表达式替换为如下函数调用:
*((type*)(__MNT_CHK_AAV(p+expr,__MNT_CHK_AAV_B_n,__MNT_CHK_AAV_E_n,filename,loc)))
其中,函数参数p+expr表示数组下标表达式访问的内存地址,函数参数__MNT_CHK_AAV_B_n表示第n个形式参数的起始地址,函数参数__MNT_CHK_AAV_E_n表示第n个形式参数的结束地址,函数参数filename表示源文件名,函数参数loc表示代码行号;
操作333、如果q是不满足以上操作331、操作332中的两种情况的指针,则认为源代码中存在指针使用前未赋初值的错误,并报错;
操作4、如果结点s是一个指针访问表达式*expr,其中expr为表达式,且expr中包含一个支配指针p,则根据p的类型分别进行如下操作:
操作41、如果p是符号表中已定义的一个数组,则从符号表中获取该数组的类型type和长度len,然后将该表达式替换为如下函数调用:
*((type*)(__MNT_CHECK_AAV(expr,p,p+len,filename,loc)))
其中,函数参数expr表示指针访问表达式访问的内存地址,函数参数p表示数组的起始地址,函数参数p+len表示数组的结束地址,函数参数filename表示源文件名,函数参数loc表示代码行号;
操作42、如果p是所在函数声明的第n个形式参数,则从符号表中获取该指针的类型type,然后将该表达式替换为如下函数调用:
*((type*)(__MNT_CHK_AAV(expr,__MNT_CHK_AAV_B_n,__MNT_CHK_AAV_E_n,filename,loc)))
其中,函数参数expr表示指针访问表达式访问的内存地址,函数参数__MNT_CHK_AAV_B_n表示第n个形式参数的起始地址,函数参数__MNT_CHK_AAV_E_n表示第n个形式参数的结束地址,函数参数filename表示源文件名,函数参数loc表示代码行号;
操作43、如果p是不满足以上操作41、操作42中的两种情况的指针,则从指针依赖图中获取其最终依赖指针q,如果q不存在,则认为源代码中存在指针使用前未赋初值的错误,并报错,如果q存在,则根据q的类型分别进行如下操作:
操作431、如果q是符号表中已定义的一个数组,则从符号表中获取指针p的类型type和数组q的长度len,然后将该表达式替换为如下函数调用:
*((type*)(__MNT_CHECK_AAV(expr,q,q+len,filename,loc)))
其中,函数参数expr表示指针访问表达式访问的内存地址,函数参数q表示数组的起始地址,函数参数q+len表示数组的结束地址,函数参数filename表示源文件名,函数参数loc表示代码行号;
操作432、如果q是所在函数声明的第n个形式参数,则从符号表中获取指针p的类型type,然后将该表达式替换为如下函数调用:
*((type*)(__MNT_CHK_AAV(expr,__MNT_CHK_AAV_B_n,__MNT_CHK_AAV_E_n,filename,loc)))
其中,函数参数expr表示指针访问表达式访问的内存地址,函数参数__MNT_CHK_AAV_B_n表示第n个形式参数的起始地址,函数参数__MNT_CHK_AAV_E_n表示第n个形式参数的结束地址,函数参数filename表示源文件名,函数参数loc表示代码行号;
操作433、如果q是不满足以上操作431、操作432中的两种情况的指针,则认为源代码中存在指针使用前未赋初值的错误,并报错;
操作5、如果结点s是一个函数声明或函数定义表达式type func(…,type_nexpr_n,…),其中:第n个参数表达式expr_n为type_n类型的数组或指针声明p,省略号…表示其它参数表达式,则将该函数声明或函数定义替换为如下函数:
type func(…,type_n expr_n,void*__MNT_CHK_AAV_B_n,void*__MNT_CHK_AAV_E_n,…)
其中,省略号…表示原来的所有参数表达式,函数参数__MNT_CHK_AAV_B_n表示第n个参数表达式的起始地址,函数参数__MNT_CHK_AAV_E_n表示第n个参数表达式的结束地址;
操作6、如果结点s是一个函数调用表达式func(…,expr_n,…),其中:第n个参数表达式expr_n中包含一个支配指针p,省略号…表示其它参数表达式,则根据p的类型分别进行如下操作:
操作61、如果p是符号表中已定义的一个数组,则从符号表中获取该数组的长度len,然后将该表达式替换为如下函数调用:func(…,expr_n,p,p+len,…),其中,省略号…表示原来的所有参数表达式,函数参数p表示数组的起始地址,函数参数p+len表示数组的结束地址;
操作62、如果p是所在函数声明的第n个形式参数,则将该表达式替换为如下函数调用:
func(…,expr_n,__MNT_CHK_AAV_B_n,__MNT_CHK_AAV_E_n,…)
其中,省略号…表示原来的所有参数表达式,函数参数__MNT_CHK_AAV_B_n表示第n个形式参数的起始地址,函数参数__MNT_CHK_AAV_E_n表示第n个形式参数的结束地址;
操作63、如果p是不满足以上操作61、操作62中的两种情况的指针,则从指针依赖图中获取其最终依赖指针q,如果q不存在,则认为源代码中存在指针使用前未赋初值的错误,并报错,如果q存在,则根据q的类型分别进行如下操作:
操作631、如果q是符号表中已定义的一个数组,则从符号表中获取数组q的长度len,然后将该表达式替换为如下函数调用:func(…,expr_n,q,q+len,…),其中,省略号…表示原来的所有参数表达式,函数参数q表示数组的起始地址,函数参数q+len表示数组的结束地址;
操作632、如果q是所在函数声明的第n个形式参数,则将该表达式替换为如下函数调用:
func(…,expr_n,__MNT_CHK_AAV_B_n,__MNT_CHK_AAV_E_n,…)
其中,省略号…表示原来的所有参数表达式,函数参数__MNT_CHK_AAV_B_n表示第n个形式参数的起始地址,函数参数__MNT_CHK_AAV_E_n表示第n个形式参数的结束地址;
操作633、如果q是不满足以上操作631、操作632中的两种情况的指针,则认为源代码中存在指针使用前未赋初值的错误,并报错。
该专利技术资料仅供研究查看技术是否侵权等信息,商用须获得专利权人授权。该专利全部权利属于南京航空航天大学,未经南京航空航天大学许可,擅自商用是侵权行为。如果您想购买此专利、获得商业授权和技术合作,请联系【客服】
本文链接:http://www.vipzhuanli.com/pat/books/201410022323.0/1.html,转载请声明来源钻瓜专利网。