一种内存访问异常的检测方法及装置的制造方法_3

文档序号:8319069阅读:来源:国知局
…vn},vi与源程序内的独立的函数--映射并被其属性刻画。vi的属性集合 为{region, func, ···,file},region用于标记程序是本文件内使用,还是全局使用,func、 file分别代表函数名和所在文件名。vi的出度和入度取决于函数的调用关系,且出度 和入度均为〇的节点为死代码可被直接删除。边集合E(G) = {el,e2,e3…en},若ei = {〈vj, vk>|vj, vk e V(G)},则ei是一条以vj为初节点,以vk为终节点的有向边,它描述了 vj, vk之间存在的调用关系,ei的属性集合为{cond, · · ·,seq},其中,cond代表vj调用vk 的谓词条件,seq为ei位于同一个节点vj上全部的出弧上的序值,即函数调用的逻辑序关 系。关联函数φ(〇)描述了边与节点之间的关联关系E -VXV,CallGraph中V(G)内各节 点元素之间存在不定数量的边。因此,qp(G)即不是单映射也不是满映射。
[0084] 本申请实施例提供的一种内存访问异常的检测方法,如图4所示,所述根据所述 全局函数调用图、所述第二列表文件和所述数据依赖图,对所述源代码进行动态内存分配 的匹配性检测,包括:
[0085] S123 :根据所述第二列表文件,对所述全局函数调用图内的节点进行区分标记;
[0086] S124 :提取所述全局函数调用图内的入口函数节点,通过分析所述数据依赖图,向 前追溯并提取与所述动态内存分配库函数存在数据依赖的前驱节点,删除其它节点;
[0087] S125:将每个提取的节点在所述全局函数调用图中的前驱节点与后继节点重新建 立连接关系,且保持逻辑序关系不变,生成精简函数调用图;
[0088] S126 :如果任意一个节点内存在针对同一变量的动态内存分配库函数,则向该节 点添加自旋弧,并删除所述精简函数调用图内由于所述自旋弧出现自闭环的边,对所述源 代码进行动态内存分配的匹配性检测。
[0089] 程序员一般是调用标准库函数malloc和free实现对内存空间的动态申请和释 放,其中,malloc函数的实现机制是通过建立链表结构,管理和组织内存中离散的内存片 段,并以内存片段的首地址以及长度作为节点属性。free函数则是根据用户输入的内存地 址,查找链表内的节点,并对目标内存片段进行删除。工程领域中,进行动态内存分配时,较 常见的错误有下述几种:
[0090] 1、程序运行期动态申请内存后,由于程序执行异常导致中断,而出现的对已申请 的内存空间不释放;2、程序员的疏忽致使的未使用free函数对动态申请的内存进行显式 释放,而出现的内存泄漏;3、由于程序控制流的影响,对同一内存片段进行多次显式释放; 4、程序员释放非法内存地址。
[0091] 基于上述现状,本发明提出的技术方案,在进行的动态检测之前,还从宏观上对 malloc、free函数进行匹配性检测,这主要是为了降低后续操作计算量。为了实现这一目 标,本发明分多步操作实施,工作流程如图4所示。
[0092] 具体的,在进行匹配性检测前,根据代码分析模块输出的第二列表文件,对 CallGraph内的节点进行区分标记;保留CallGraph结构内的入口函数节点,一般为main 函数,否则将形成森林结构;保留CallGraph内被标记的节点,通过分析数据依赖图,向前 追溯与malloc、free函数存在数据依赖的前驱节点,并保留;
[0093] 删除上述被保留以外的全部节点,并将当前节点在图中的前驱节点与后 继节点重新建立连接关系,且其中的逻辑序关系保持不变,并生成精简函数调用图 1^(11^(^116四口11。假设存在以下关系{¥111,¥1^},{¥1^11},但不存在{¥111,¥11},其中,¥代表 CallGraph内的一个节点,vm为vk的一个前驱节点,vk为vn的一个前驱节点,假设vk被 删除,那么,在本发明提出的技术方案中将建立vm与vn之间的连接关系,而vm则成为vn 的一个前驱节点;
[0094] 如果任一个节点内,存在针对同一变量的malloc与free函数,则向该节点添加自 旋弧;
[0095] 由于函数间可能存在递归调用,这就导致函数调用图内存在由多个节点组成 的环路,然而,程序的执行行为与数据激励密不可分,程序的循环次数却有可能是由运 行时参数决定。为了更加深入的对导致内存泄露的症结进行排查,本发明还删除了 ReducedCallGraph结构内导致出现自闭环的边,因此,ReducedCallGraph在不考额外添加 的自旋弧的条件下是一个有向无环图。
[0096] ReducedCallGraph生成结束后,开始进行匹配性检测。首先,从main函数开始, 进行深度优先遍历,即获取从入口节点到出口节点的各条路径{Pathi, Path2, . . .,Pathn}; 其次,基于数据依赖关系,分析全局文件内的malloc、free函数之间多对多的映射关系;然 后,根据程序的谓词关系,分析路径Pathi是否有效;最后,查询Pathi下的malloc、free是 否匹配,如果不匹配,则进行报告,否则继续下一条路径的匹配性检测。
[0097] 步骤S13 :构建虚拟执行平台,根据所述第一列表文件、所述控制流图和所述数据 依赖图提取执行路径,实现对动态内存分配造成的内存泄露以及程序运行时的内存访问越 界的检测操作。
[0098] 常见的与平台相关的集成开发环境,如Visual Stdio等在处理内存访问异常时, 是配合硬件中断而实现,如未分配的内存区的初始化数据为Oxcdcdcdcd,它代表中断1。然 而,针对一些特殊场景,如银行业的代码投产之后,如果内存访问出现异常,将导致生产故 障,后果难以估量。
[0099] 本申请实施例提供的一种内存访问异常的检测方法中,所述构建虚拟机平台,包 括:选择目标处理器平台,基于指令集功能特征,建立指令行为级模拟器;建立所述指令行 为级模拟器的过程中,针对条件判断类及分支跳转类指令进行行为级建模时,添加先进后 出的堆栈结构;所述堆栈结构用于保存所述条件判断类及分支跳转类指令的内存地址、寄 存器内的数据的逆状态。
[0100] 为了构建一个能对代码中内存访问异常进行充分检测的环境与平台,本发明还建 立一套虚拟机平台。公知技术可知,编译器、汇编器、链接器只是用于将高级程序源代码,分 多步骤翻译为目标平台可读的二进制机器码,但不改变程序的正常执行逻辑。为了降低虚 拟执行时的时间开销,本发明ARMlO处理器的RISC指令集做为目标平台,并配备了相应的 模拟器。这主要源于,ARM系列处理器有很好的平台支持,且指令集设计十分规范,有利于 加速虚拟执行的效率,但本发明并不受限于此,用户可根据实际情况选用相应的平台。
[0101] 本申请实施例提供的一种内存访问异常的检测方法,如图5所示,所述根据所述 第一列表文件、所述控制流图和所述数据依赖图提取虚拟执行路径,实现对动态内存分配 造成的内存泄露以及程序运行时的内存访问越界的检测操作,包括:
[0102] S131 :对程序进行虚拟执行,判断是否出现条件判断类及分支跳转类指令,如果出 现,保存所述条件判断类及分支跳转类指令的内存地址、寄存器内的数据的逆状态,并进行 入栈;统计当前执行路径下申请和释放的动态内存的字节数,统计对内存的写操作,并把 对内存的修改写入栈顶记录所对应的内存状态修改链表内;当程序执行到出口函数时,检 查申请和释放的动态内存的字节数是否相同,并根据内存地址,查找导致内存泄露的动态 内存分配库函数;检测完成后,从所述栈结构内读取一条记录,并对虚拟机的程序指针、内 存、寄存器进行恢复;程序运行到栈空为止,实现对动态内存分配造成的内存泄露的检测操 作;
[0103] S132 :获得所述第一列表文件内的静态数组占用以及动态申请的内存的内存记 录,在链接期对静态分配的全局数据、局部静态数组分配内存地址,在运行期通过压栈操作 计算存储于程序栈内的局部未初始化数组的栈地址的偏移量,并通过动态内存分配库函数 的返回值获取动态内存分配的内存块;每一条独立的加载、保存指令在函数内的基本块中 首次被执行时,记录访问的内存地址以及所在的内存块,当下一次访问中的目标内存地址 不在所述内存块内时,判定为内存访问越界,实现对程序运行时的内存访问越界的检测操 作。
[0104] 虚拟执行平台在本发明中完成内存泄露、内存访问越界两方面检测工作。由于程 序的执行行为与数据激励密不可分,不同数据输入模式下,程序流也千差万别,这就是说内 存访问异常在不同数据激励下可能是不可重现的。在虚拟平台上,所有的对程序运行逻辑 的修改都是可控的,为此,本发明还提出了一种全路径的执行方法,该方法是通过在指令级 行为进行修改实现的。
[0105] 以RISC体系结构为例,分支判断通常是配合条件判断指令以及推断寄存器实现, 这也就是说,如果通过修改条件判断指令的结果,将可以直接修改程序的控制流,以下述两 条指令为例,
[0106] prOlt prl, pr2, dl, 12. 1)
[0107] prlcall func. 2)
[0108] 当数据寄存器dl>12时,分支指令2将被执行,否则,分支不被发生。因此,本文在 虚拟机中对条件判断类及分支跳转类指令还添加了先进后出的堆栈结构,其中,栈内存储 的记录包括{指令内存地址,内存数据,寄存器数据}。
[0109] 虚拟执行时检测内存泄露的执行流程具体如下所示:
[0110] (1)虚拟机执行时,一但出现条件判断类及分支跳转类指令,将该指令的内存地 址、当前指令相关的寄存器内的数据的逆状态(如指令1中,假设dl的值为14,指令1执行 成功,那么dl被保存的数据为12),其余无关寄存器的数据、而内存数据则当下一次出现内 存修改时才进行保存,并将上述数据进行入栈;
[0111] ⑵程序继续运行,直到出口函数为止;
[0112] (3)程序运行过程中,统计当前执行路径下申请和释放的动态内存的字节数;
[0113] (4)程序运行过程中,还需统计对内存的写操作,并把对内存的修改写入栈顶记录 所对应的内存状态修改链表内;
[0114] (5)当程序执行到出口函数时,检查申请和释放的动态内存的字节数是否相同,并 根据内存地址,找出具体导致内存泄露的malloc、free函数的为止;
[0115] (6)检测完成后,从所述栈结构内读取一条记录,并对虚拟机的程序指针、内存、寄 存器进行恢复;
[0116] (7)程序运行到栈空为止。
[0117] 内存访问越界分读、写越界两种,而所有的内存操作都对应于两类机器指令load 和store。因此,本文在虚拟机中对目标指令集进行行为级建模、以及链接期新增了功能,而 这些添加部分遵循如下两条约束实施,一方面,不能影响程序的执行逻辑,另一方面,需要 在程序的运行期判断是否出现访问越界。
[0118] 本发明进行内存访问越界检测的具体步骤如下所示:
[0119] (1)读取代码分析模块所获得的第一列表文件所存取的静态数组占用以及动态 申请的内存的内存记录,而链接期只能对其中静态分配的全局数据、局部静态数组分配内 存地址,而局部未初始化的数
当前第3页1 2 3 4 5 
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1