用于易变数据结构程序验证的形状图生成方法及装置
文献发布时间:2023-06-19 09:36:59
技术领域
本发明涉及C语言程序验证技术领域,具体涉及用于易变数据结构程序验证的形状图生成方法及装置。
背景技术
基于演绎推理的形式化验证主要用于提高软件的可信度。在形式化验证系统对C语言程序的验证过程中,会遇到各种易变数据结构,而这类程序因其动态生成、结构复杂难以仅用一阶逻辑公式来表述,为此陈意云教授及其研究团队提出了用于描述各种易变数据结构的形状图逻辑。
形状图是描述易变数据结构中指针类型的域变量的指向的一种有向图,准确表达了指针指向的内存块的存在和指针间的相等/不等关系,因而可作为操作指针的程序中指针有效性和相等性的断言。形状图逻辑是Hoare逻辑的一种扩展,形状图逻辑将易变数据结构上大量指针之间的关系的断言概括抽象为等价的形状图,并在霍尔逻辑的基础上添加形状图的逻辑规则,形状图作为断言的一部分参与每一条程序语句的相应逻辑演算,从而大大简化含易变数据结构的程序验证。
现有技术中形状图逻辑存在的问题包括:
1.描述形状图的断言仅有\c_dlist、\tree_seg_l等基本形状内置谓词,描述能力太弱。完全不能满足实际程序中对形状图描述的要求。
2.当形状图的数据断言中的指针路径包含环时,存在无法将对应结构体翻译为代数数据类型的问题。
3.对指针别名的判断的实现未作优化,尽管实际需要修改的指针别名只有一小部分,每次指针操作语句引起的形状图变化时都需要对断言中的所有指针路径进行别名判断,增加了实现的复杂度和验证时间。
4.未提及当用户自定义谓词涉及指针时,谓词在形状图逻辑下如何进行逻辑演算。
发明内容
针对上述现有技术存在的问题,本发明提供了一种用于易变数据结构程序验证的形状图生成方法,包括如下步骤:
细化不同种类易变数据结构断言,并对细化后的断言种类简化断言描述方法;
按照预设优化顺序对不同断言种类进行形状图构造获取程序的初步形状图,所述不同断言种类的构造方法包括细化后的断言种类对应的形状图构造方法;
基于初步构造的形状图进行修正优化获取精准形状图。
作为上述方案的进一步优化,所述细化不同种类易变数据结构断言,包括:
遍历语法树,获取所有程序断言;
将断言范式化为析取范式,将每个析取分支的断言分拆为合取子式,每个子式分类为形状断言、数据断言、符号断言;
所述形状断言进一步分为形状内置谓词、表和环长度断言、指针距离断言、指针等于空断言、指针不等于空断言、指针相等断言、指针不等断言、悬空指针断言;
所述数据断言依据指针路径进一步分为一般指针、数据域指针、量化数据域指针、谓词指针、谓词数据域指针。
作为上述方案的进一步优化,所述对细化后的断言种类简化断言描述方法,包括:
对于数据断言中指针取指针域连续取多次的情况,记为折叠指针域,通过新增p->(r:n)描述p指针取指针域r连续取了n次,n不小于0,所述折叠指针域的断言描述方法用于两个指针距离的断言和数据断言中,并且路径不会构成环。
作为上述方案的进一步优化,所述对细化后的断言种类简化断言描述方法,还包括:
对于形状断言中的表和环长度断言,通过新增内置形状谓词\length描述表和环长度,\length(p,r)表示p沿r指针域一直访问回到自身或访问到空节点时经过的节点数,如果p为空节点,则\length(p,r)等于0。
作为上述方案的进一步优化,所述对细化后的断言种类简化断言描述方法,还包括:
对于悬空指针断言,通过新增内置形状谓词\dangling描述悬空指针。
作为上述方案的进一步优化,所述细化后的断言种类对应的形状图构造方法,包括:对于指针相等断言,采用合并断言等式两边节点的方式进行形状图的构造。
作为上述方案的进一步优化,所述指针相等断言的形状图构造方法包括如下步骤:
将节点的出边指向的节点中暂时未构造的节点设为未知节点;
根据等式两边的节点类型将两个节点分为主体节点和客体节点,类型优先级从低到高依次为:悬空节点、空节点、谓词节点、结构节点、浓缩节点,优先级高的节点作为主体节点;
若等式两边的主体节点和客体节点是同一节点,则直接确定合并成功;
若客体节点是悬空节点,则将客体节点入边转移至主体节点,删除客体节点;
若主客体节点都为空节点,则直接确定合并成功;
若主客体节点都为结构节点,则将客体节点入边转移至主体节点,再对所有一一对应的出边指向的节点递归合并节点,有一个出边合并失败则当前节点合并失败,合并成功后删除客体节点;
若主体节点为浓缩节点,同时客体节点为结构节点且结构节点对应浓缩节点方向的出边指向入度1的悬空节点,这条出边不进行递归合并,合并成功后删除客体节点;
若客体节点为谓词节点,同时主体节点为结构节点且结构节点所有出边指向入度1的悬空节点,将主体节点所有出边指向的悬空节点替换为谓词节点,删除客体节点;
非上述情况则直接确定合并失败。
作为上述方案的进一步优化,所述细化后的断言种类对应的形状图构造方法,还包括:对于指针距离断言的形状图构造方法包括如下步骤:
对于指针p和q,p沿next域到q的距离为n,则找到两个指针p、q在形状图上对应非悬空节点,计算p沿next域到q的距离的表达式e,合取e==n到当前子图的符号断言,p沿next域访问不到q则删除当前子图,找不到非悬空节点则按整体描述构造q。
作为上述方案的进一步优化,所述细化后的断言种类对应的形状图构造方法,还包括对于数据断言中用户自定义谓词的形状图构造方法为,提取其中的基本形状内置谓词,基于提取的基本形状内置谓词构造形状图,所述形状提取方法为:
获取自定义谓词参数间的依赖关系,所述依赖关系指根据谓词定义描述,某个谓词指针参数经过至少一次指针域访问后等于另一个谓词指针参数;
判断每个参数是不是对应形状的表头或树根,如果是,则确定自定义谓词的的基本形状内置谓词,否则,进入下一步;
将指针参数作为表段头或树段头,根据依赖关系获取每个依赖该指针参数p的指针参数q,并利用定理验证器获取指针参数p对应的表段尾或树段尾的指针参数q,获取自定义谓词的基本形状内置谓词。
作为上述方案的进一步优化,所述获取谓词参数间的依赖关系的方法为:
将参数和谓词的直接引用作为长0的有向边,指针域引用作为长1的有向边;
根据图论问题求解方法求解参数对应节点是否有到达其他节点的长度大于0的路径。
作为上述方案的进一步优化,所述按照预设优化顺序对不同断言种类进行形状图构造获取程序的初步形状图,包括:
(111)基于范式化后的所有断言生成易变数据结构的节点和指针指向,包括:
对出现的不含折叠域的指针路径构造路径上的所有节点;
添加指针折叠域折叠次数不小于0的断言;
检查当前断言是否矛盾,矛盾则中止构造形状图;
根据基本形状内置谓词构造形状;
根据自定义谓词提取的每一个基本形状内置谓词,将当前形状图复制为两份,一份尝试构造形状图,一份不用于构造形状图,删除构造失败的子图;
(112)还原缺失的指针指向关系,包括:
根据指针相等断言构造形状图;
(113)删除或者修正不符合断言描述的形状子图,包括:
根据指针距离断言构造形状图;
检查形状图上的浓缩节点,浓缩节点成环的,添加环的总长大于0断言,浓缩节点成链且结尾为空节点的,添加链的总长大于0断言;
根据指针等于空断言构造形状;
根据自定义谓词提取的每一个基本形状内置谓词检查当前形状图是否符合形状;
根据指针不等于空断言构造形状;
根据指针不等断言构造形状;
根据表和环长度断言,计算形状图上对应长度,用对应长度表达式替换当前子图断言中的\length谓词;
根据悬空指针断言检查形状,删除未显式声明的悬空节点的子图;
检查当前断言是否矛盾,剔除矛盾子图。
作为上述方案的进一步优化,所述基于初步构造的形状图进行修正优化获取精准形状图,包括对指针路径去环和消除指针别名。
作为上述方案的进一步优化,所述对指针路径去环过程中,对于用户自定义谓词的指针路径去环采用直接删除描述环的指针关系。
作为上述方案的进一步优化,所述对于非用户自定义谓词的指针路径去环和消除指针别名,采用的方法为基于形状图构造生成树,将数据断言中的指针路径替换为指针路径对应节点在生成树上的路径,利用生成树没有环且生成树上到达任一节点的路径唯一的原理实现指针路径的去环和别名消除。
作为上述方案的进一步优化,所述利用生成树实现指针路径去环和别名消除的方法为:
基于形状图构造生成树;
根据数据断言中的不含约束变元的最长指针路径前缀,在生成树上查找到唯一对应节点;
将数据断言中的指针路径A替换为所述唯一对应节点在生成树上的唯一路径B;
保存节点与数据断言中指针路径的双向绑定,动态维护生成树。
作为上述方案的进一步优化,所述基于初步构造的形状图进行修正优化获取精准形状图,还包括:对赋值语句前后断言的谓词是否展开进行判断,所述判断方法包括:
获取谓词描述的范围;
判断赋值语句对于指针域或数据域的修改是否影响谓词描述;
若是,则进行谓词展开。
作为上述方案的进一步优化,所述获取谓词描述的范围,具体包括:
获取谓词中迭代的指针参数的域和所有出现的域引用的域名和类型,所述迭代的指针参数的域为根据谓词定义描述,参数在谓词中可能直接访问的域,所述域引用的域名和类型对应匹配;
在形状图上从指针实参开始,对实参对应的迭代的域取一次引用的结果再递归取谓词中出现的所有域引用;
获取所有访问过的节点、边、数据作为谓词描述的范围。
作为上述方案的进一步优化,所述获取谓词中迭代的指针参数的域的方法为:
将参数和谓词的直接引用作为虚的有向边,指针域引用和数据域引用作为实的有向边;
利用图论中的求解方法求解参数对应节点可达实边的种类的方法获取所有参数的迭代的域。
作为上述方案的进一步优化,所述对实参对应的迭代的域取一次引用的结果再递归取谓词中出现的所有域引用时,包括:
判断谓词中是否包含表段或树段的形状;
若不包含则直接对实参对应的迭代的域取一次引用的结果再递归取谓词中出现的所有域引用,否则进入下一步;
若谓词中包含表段或树段的形状,则当该实参对应段的头,递归引用到达段尾对应的实参指向的节点时,不再对段尾继续递归,并对段做迭代域补充。
作为上述方案的进一步优化,所述对段做迭代域补充的方法为:
依据谓词中的形状描述构造简化的形状图,将谓词定义中的谓词引用记录到实参对应的节点上,同时记录该节点对应的形参位置;
对谓词定义中所有节点上的自引用节点,分别统计穿过各个形参一次域引用的所有域引用;
获得各个形参一次域引用的所有域引用后,对每个形参在当前谓词所有分支上查找一次域引用,再对所有域引用递归查找,其中,对于自引用节点的所有域引用递归查找时,包括借由谓词引用递归查找;
对查找到的节点检查有无别的形参直接指向,所有直接指向这些节点的形参补充所有域引用到迭代的域。
作为上述方案的进一步优化,所述对穿过各个形参一次域引用的所有域引用的统计方法为:
对穿过自引用的出边记为一次域引用,所述出边指向的形状描述部分递归获取所有域引用,将所述递归获取的所有域引用记录到该出边对应一次域引用的所有域引用下面;
对该自引用的节点上的其他谓词引用,根据节点对应的谓词形参,获得其他谓词下的迭代的域和所有域引用,将其加入对应形参一次域引用的所有域引用。
本发明还提供了一种电子设备,其特征在于,所述电子设备包括:
存储器,用于存储可执行指令;
处理器,用于运行所述存储器存储的可执行指令时,实现上述用于易变数据结构程序验证的形状图生成方法。
本发明的用于易变数据结构程序验证的形状图生成方法,具备如下有益效果:
1.本发明扩展现有形状图逻辑的实现技术,为描述形状图的形状断言添加了更多语法支持,包括指针折叠域、两个指针距离的断言描述、描述表和环长度的内置谓词、指针相等/不等断言、悬空指针断言,并且为新增断言类型划分明确的操作语义。
2.本发明通过优化不同断言类型的构建顺序对形状图构造方法进行改进,实现形状图构造的简单化。
3.本发明通过对用户自定义谓词提取其中的基本形状内置谓词,并基于提取结果构造形状图,解决内置形状谓词引入后带来的负面影响,其中提取方法通过谓词参数间的依赖关系,依赖关系实现快速检查谓词形状。
4.本发明对形状图的数据断言中的指针路径包含环的情况,通过构造形状图的生成树,将路径替换为节点在生成树上对应的路径,进行去环,使易变数据结构类型能翻译为代数数据类型。
5.本发明通过利用形状图生成树,对断言中指针路径与节点的双向绑定,并动态维护生成树,优化指针别名消除过程,减少了指针操作语句演算过程中需要修改的别名数量。
6.本发明对谓词的展开通过对赋值语句前后谓词描述范围的判断实现惰性展开,采用的对谓词描述范围的判断方法,一方面确保获取的谓词描述的范围一定包含整个谓词真实描述的范围,从而保证程序验证结果是可靠的,另一方面,获取的谓词描述的范围一定被包含于仅简单根据谓词中出现的域递归搜索的范围,从而减少程序验证结果误报率。
附图说明
图1为本发明中按照预设优化顺序对不同断言种类进行形状图构造获取初步形状图的方法流程图;
图2为本发明中对指针相等断言的一种情况下的形状图构造方法图示;
图3为本发明中对指针相等断言的另一种情况下的形状图构造方法图示;
图4为本发明中以一个具体数据为例,获取谓词参数间的依赖关系的方法图示;
图5为本发明中以一个具体数据为例,获取所有参数的迭代的域的方法图示;
图6-图10为以一个具体数据为例,在形状图上从指针实参开始,对实参对应的迭代的域取一次引用的结果再递归取谓词中出现的所有域引用的过程图示;
图11-图14为以另一个具体数据为例,在形状图上从指针实参开始,对实参对应的迭代的域取一次引用的结果再递归取谓词中出现的所有域引用的过程图示。
具体实施方式
为了使本发明的目的、技术方案和优点更加清楚,下面将结合附图对本发明作进一步地详细描述,所描述的实施例不应视为对本发明的限制,本领域普通技术人员在没有做出创造性劳动前提下所获得的所有其它实施例,都属于本发明保护的范围。
对本发明实施例进行进一步详细说明之前,对本发明实施例中涉及的程序验证过程进行简单说明。
1、对一个C语言文件进行程序验证的过程
安全C语言验证是以一个C源文件(包括了C源文件中包含的一些头文件)为单位产生语法树并进行生成验证条件的演算的过程。对于一个C程序源文件,验证条件生成器依次扫描常量定义、类型定义、变量声明、函数声明和函数定义,然后做下面的处理:
(11)对于外部变量(及常量)声明和静态外部变量(及常量)声明,按其所置初值生成相应变量的断言,作为操作系统调用main函数时的断言的一部分。需要注意的是,main函数是最后一个被验证的函数。
(12)对于函数声明,处理其函数协议时,将其函数协议添加到该函数的协议表上。函数可能有多个声明,因为每一个函数声明都可以有一个函数协议,所以一个函数可能有多个函数协议,每个函数协议都需要单独验证。
(13)对于函数定义,处理其函数协议时,将其函数协议添加到该函数的协议表上,然后对函数协议表上的每一个函数协议进行生成验证条件的演算。
2、对一个函数进行程序验证的过程
为一个“函数定义”进行产生验证条件的演算的整体过程如下(如果函数有多个协议则每个协议都需要经过下面同样的过程):
(21)在函数入口处,验证条件生成器需要根据函数协议产生函数入口处断言。
(22)然后使用复合语句演算规则对函数体进行演算得到函数出口处断言,在函数体语句的演算过程中也会产生一系列的验证条件。
(23)根据演算得到的函数出口断言和函数协议产生函数出口处验证条件。复合语句演算规则和函数出口处验证条件的产生将在下文详细介绍。下面介绍在函数入口处,根据函数协议产生函数入口处断言的基本过程:
(211)根据前端模块提供的接口获取函数协议中的requires子句中的断言R;
(212)将R断言进行范式化,范式化的结果为R
(213)根据前端模块提供的接口判断被验证的函数是否是堆指针操作函数,如果是,则根据形状分析方法对于每个R
(214)对于每个R
经过以上几个步骤之后,函数入口处的断言形式为:
(P
本申请实施例主要是对上述步骤(213)中所述的形状分析方法进行改进,实现形状图的精确构造以及简化构造,进而提高形状图用于程序验证过程中的程序验证准确性和验证速度。
具体的,本申请实施例提供的用于易变数据结构程序验证的形状图生成方法,包括如下步骤:
细化不同种类易变数据结构断言,并对细化后的断言种类简化断言描述方法;
按照预设优化顺序对不同断言种类进行形状图构造获取程序的初步形状图,所述不同断言种类的构造方法包括细化后的断言种类对应的形状图构造方法;
基于初步构造的形状图进行修正优化获取精准形状图。
本申请实施例细化断言种类以及采用新增内置形状谓词描述对应断言,使得复杂形状图的描述更加规范简练,在此基础上,为细化后的断言种类采用对应的不同的形状图构造方法,提供更加严格的约束,使得形状系统更好地发现断言中的错误;并且基于不同断言种类改进构造顺序,简化构造过程,避免每一步的形状图构造过程中产生过多不必要的子图导致后续构造过程中的繁琐。
具体来说,细化不同种类易变数据结构断言的过程包括:
遍历语法树,获取所有程序断言;
将断言范式化为析取范式,将每个析取分支的断言分拆为合取子式,每个子式分类为形状断言、数据断言、符号断言;
所述形状断言进一步分为形状内置谓词、表和环长度断言、指针距离断言、指针等于空断言、指针不等于空断言、指针相等断言、指针不等断言、悬空指针断言;
所述数据断言依据指针路径进一步分为一般指针、数据域指针、量化数据域指针、谓词指针、谓词数据域指针。
对于上述两个指针距离的断言和数据断言中,指针取指针域连续取多次的情况,增加了折叠指针域的概念,采用p->(r:n)描述p指针取指针域r连续取了n次,n不小于0,简化指针路径描述方法,并且路径不会构成环,比如q==p->(next:n)表示p沿着next域连续取了n次,即p和q两个指针距离为n。
对于上述形状断言中的表和环长度断言,通过新增内置形状谓词\length描述表和环长度,\length(p,r)表示p沿r指针域一直访问回到自身或访问到空节点时经过的节点数,如果p为空节点,则\length(p,r)等于0。对于表和环长度断言的描述,例如\length(p,next)=n,表示p沿r指针域一直访问回到自身或访问到空节点时经过的节点数为n,当然\length(p,r)不限于出现在等式断言中。在形状图构造过程中,对于表和环长度断言的处理方法为若对应表或环的长度不符合断言,则删除对应子图。
对于上述悬空指针断言,通过新增内置形状谓词\dangling描述悬空指针。\dangling(p->next)表示p->next为悬空指针,在形状图构造过程中,含有未用\dangling显式声明的悬空节点的子图需被删除。
对于上述指针相等断言,采用合并断言等式两边节点的方式进行形状图的构造,具体包括如下步骤:
将节点的出边指向的节点中暂时未构造的节点设为未知节点;
根据等式两边的节点类型将两个节点分为主体节点和客体节点,类型优先级从低到高依次为:悬空节点、空节点、谓词节点、结构节点、浓缩节点,优先级高的节点作为主体节点;
若等式两边的主体节点和客体节点是同一节点,则直接确定合并成功;
若客体节点是悬空节点,则将客体节点入边转移至主体节点,删除客体节点;
若主客体节点都为空节点,则直接确定合并成功;
若主客体节点都为结构节点,则将客体节点入边转移至主体节点,再对所有一一对应的出边指向的节点递归合并节点,有一个出边合并失败则当前节点合并失败,合并成功后删除客体节点;
若主体节点为浓缩节点,同时客体节点为结构节点且结构节点对应浓缩节点方向的出边指向入度1的悬空节点,这条出边不进行递归合并,合并成功后删除客体节点;
若客体节点为谓词节点,同时主体节点为结构节点且结构节点所有出边指向入度1的悬空节点,将主体节点所有出边指向的悬空节点替换为谓词节点,删除客体节点;
非上述情况则直接确定合并失败。
参见图2和图3,对指针相等断言的合并过程进行说明,其中圈1内为主体,圈2内为客体,白色节点为结构节点,灰色节点为浓缩节点,D指悬空节点,N指空节点。
对于上述指针距离断言的形状图构造方法包括如下步骤:
对于指针p和q,p沿next域到q的距离为n,则找到两个指针p、q在形状图上对应非悬空节点,计算p沿next域到q的距离的表达式e,合取e==n到当前子图的符号断言,p沿next域访问不到q则删除当前子图,找不到非悬空节点则按整体描述构造q。
对于数据断言中用户自定义谓词的形状图构造方法为,提取其中的基本形状内置谓词,基于提取的基本形状内置谓词构造形状图,所述形状提取方法为:
(a1)获取自定义谓词参数间的依赖关系,所述依赖关系指根据谓词定义描述,某个谓词指针参数经过至少一次指针域访问后等于另一个谓词指针参数,对于依赖关系的求解可转为图论问题求解方法,具体为将参数和谓词的直接引用作为长0的有向边,指针域引用作为长1的有向边;求解所有依赖关系的问题变为求解参数对应节点是否有到达其他节点的长度大于0的路径,这是一个图论问题,可以通过求解强连通分量再深度优先搜索等方法解决。
以定义seg(Node*p,Node*q)=p==q!=\null||p!=q&&seg(p->r,q)为例,对谓词参数间的依赖关系的判断过程进行说明,参见图4,图中虚边长度为0,实边长度为1,将参数和谓词的直接引用作为长0的有向边,指针域引用作为长1的有向边,利用图论问题求解方法求解参数对应节点是否有到达其他节点的长度大于0的路径。p有长度1的路径访问q指向的节点,而q没有长度1的路径访问q指向的节点,故q依赖于p,p不依赖于q。
(b1)在获取依赖关系后,判断每个参数是不是对应形状的表头或树根,如果是,则确定自定义谓词的的基本形状内置谓词,否则,进入下一步;
(c1)将指针参数作为表段头或树段头,根据依赖关系获取每个依赖该指针参数p的指针参数q,并利用定理验证器获取指针参数p对应的表段尾或树段尾的指针参数q,获取自定义谓词的基本形状内置谓词。
要验证一个不含环的谓词predicate(a1,a2,…,ai,…,an)的参数ai是否有形状shape(ai),只需利用定理验证器证明\forallType1a1,Type2a2,…,Typenan.(predicate(a1,a2,…,ai,…,an)==>shape(ai)),shape有多个参数的同理。例如,要验证谓词seg(Node*p,Node*q)的参数p和q是否有形状树段\tree_seg_r(p,q),只需用Z3证明\forallNode*p,Node*q.(seg(p,q)==>\tree_seg_r(p,q)),翻译到Z3的\tree_seg_r的具体定义根据内置谓词的抽象定义和用户对Node类型的域的形状声明构造。
由于形状标注的限制,一个参数在谓词中的形状只考虑是其类型的形状标注可能对应的形状(如一个参数类型的形状标注为二叉树类型,那么就不考虑其在谓词中表达单链表形状的情况),故一个参数的类型标注为基本形状,那么只考虑其作为表的头(树的根)、表段(树段)的头或尾的三种形状。
参见图1,本申请实施例中按照预设优化顺序构造初步形状图的具体步骤,包括:
(111)基于范式化后的所有断言生成易变数据结构的节点和指针指向,包括:
对出现的不含折叠域的指针路径构造路径上的所有节点;
添加指针折叠域折叠次数不小于0的断言;
检查当前断言是否矛盾,矛盾则中止构造形状图;
根据基本形状内置谓词构造形状;
根据自定义谓词提取的每一个基本形状内置谓词,将当前形状图复制为两份,一份尝试构造形状图,一份不用于构造形状图,删除构造失败的子图;
(112)还原缺失的指针指向关系,包括:
根据指针相等断言构造形状图;
(113)删除或者修正不符合断言描述的形状子图,包括:
根据指针距离断言构造形状图;
检查形状图上的浓缩节点,浓缩节点成环的,添加环的总长大于0断言,浓缩节点成链且结尾为空节点的,添加链的总长大于0断言;
根据指针等于空断言构造形状;
根据自定义谓词提取的每一个基本形状内置谓词检查当前形状图是否符合形状;
根据指针不等于空断言构造形状;
根据指针不等断言构造形状;
根据表和环长度断言,计算形状图上对应长度,用对应长度表达式替换当前子图断言中的\length谓词;
根据悬空指针断言检查形状,删除未显式声明的悬空节点的子图;
检查当前断言是否矛盾,剔除矛盾子图。
至此完成形状图的初步构造,在此基础上,对形状图进行修正优化获取精准形状图,包括对指针路径去环和消除指针别名,方法为:
(a2)对于用户自定义谓词的指针路径去环采用直接删除描述环的指针关系;如dlist_seg(Node*p,Node*q)=p==q!=\null||p!=q&&p->r->l==p&&dlist_seg(p->r,q),去掉描述环的指针关系断言后变为dlist_seg(Node*p,Node*q)=p==q!=\null||p!=q&&dlist_seg(p->r,q)。
(b2)对于非用户自定义谓词的指针路径去环和消除指针别名,采用的方法为基于形状图构造生成树,将数据断言中的指针路径替换为指针路径对应节点在生成树上的路径,利用生成树没有环且生成树上到达任一节点的路径唯一的原理实现指针路径的去环和别名消除。
步骤(b2)具体为:
基于形状图构造生成树;
根据数据断言中的不含约束变元的最长指针路径前缀,在生成树上查找到唯一对应节点(可能需要分情况讨论,使得形状图分裂,以使路径在所有子图上对应到唯一节点),举例说明最长指针路径,如\forallinti:[0..n].p->l->(r:i)->data==0的不含约束变元的最长指针路径前缀为p->l;
将数据断言中的指针路径A替换为所述唯一对应节点在生成树上的唯一路径B;
保存节点与数据断言中指针路径的双向绑定,动态维护生成树。
基于上述动态生成树,同时实现指针路径的去环和别名指针的消除,具体来说,对于别名指针涉及的程序语句,在演算过程中,各种导致形状改变的程序语句操作,分解后只有边被删除、连接边会导致生成树变更,问题变成简单的生成树动态维护问题,对生成树变更影响的那部分节点对应的指针路径替换即可。并且,在构造生成树的算法选择上,可使用构造最短路径树或最小生成树的算法,边的权值计算方式根据经验自由设置。
基于上述动态生成树保证了不论经过怎样的指针操作,断言中的指针路径都保持简洁、易读,避免了每次指针发生修改就要遍历所有数据断言的指针路径并检查指针路径是否需要修改的繁琐过程,。
本申请实施例中基于初步构造的形状图进行修正优化获取精准形状图,还包括:对赋值语句前后断言的谓词实现惰性展开,要先判断是否展开,所述判断方法包括:
获取谓词描述的范围;
判断赋值语句对于指针域或数据域的修改是否影响谓词描述;
若是,则进行谓词展开。
进一步的,上述获取谓词描述的范围,具体包括:
(a3)获取谓词中迭代的指针参数的域和所有出现的域引用的域名和类型,所述迭代的指针参数的域为根据谓词定义描述,参数在谓词中可能直接访问的域,所述域引用的域名和类型对应匹配;
(b3)在形状图上从指针实参开始,对实参对应的迭代的域取一次引用的结果再递归取谓词中出现的所有域引用;
(c3)获取所有访问过的节点、边、数据作为谓词描述的范围。
基于步骤(a3)(b3)(c3)获取谓词描述的范围的方法,首先该方法获取的谓词描述的范围一定包含整个谓词真实描述的范围,从而保证程序验证结果是可靠的(“可靠”指验证结果是“被验证的程序是对的”,则被验证的程序一定是对的)。其次,该方法获取的谓词描述的范围一定被包含于仅简单根据谓词中出现的域递归搜索的范围,从而减少程序验证结果误报率(“误报”指验证结果是“被验证的程序可能是错的”,但被验证的程序是对的的情况。)
进一步的,上述步骤(a3)中,获取谓词中迭代的指针参数的域的方法可采用转化为图论求解问题,具体的,将参数和谓词的直接引用作为虚的有向边,指针域引用和数据域引用作为实的有向边,则求解所有参数的迭代的域的问题变为求解参数对应节点可达实边的种类,这是一个图论问题,可以通过求解强连通分量再深度优先搜索等方法解决。
以定义seg(Node*p,Node*q)=p==q!=\null&&q->data==0||p!=q&&seg(p->r,q)为例,参见图5,所有参数的迭代的域的获取过程,可见p迭代的域是data和r,q迭代的域是data。
上述步骤(b3)中,对实参对应的迭代的域取一次引用的结果再递归取谓词中出现的所有域引用时,包括:
(b31)判断谓词中是否包含表段或树段的形状;
(b32)若不包含则直接对实参对应的迭代的域取一次引用的结果再递归取谓词中出现的所有域引用,否则进入(b33);
(b33)若谓词中包含表段或树段的形状,则当该实参对应段的头,递归引用到达段尾对应的实参指向的节点时,不再对段尾继续递归,并对段做迭代域补充,补充的方法为:
(b331)依据谓词中的形状描述构造简化的形状图,将谓词定义中的谓词引用记录到实参对应的节点上,同时记录该节点对应的形参位置;
(b332)对谓词定义中所有节点上的自引用节点,分别统计穿过各个形参一次域引用的所有域引用,统计方法为:
对穿过自引用的出边记为一次域引用,所述出边指向的形状描述部分递归获取所有域引用,将所述递归获取的所有域引用记录到该出边对应一次域引用的所有域引用下面;
对该自引用的节点上的其他谓词引用,根据节点对应的谓词形参,获得其他谓词下的迭代的域和所有域引用,将其加入对应形参一次域引用的所有域引用;
(b333)获得各个形参一次域引用的所有域引用后,对每个形参在当前谓词所有分支上查找一次域引用,再对所有域引用递归查找,其中,对于自引用节点的所有域引用递归查找时,包括借由谓词引用递归查找;
(b334)对查找到的节点检查有无别的形参直接指向,所有直接指向这些节点的形参补充所有域引用到迭代的域。
参见图6-14,以两个谓词定义:
seg_l(Node*p,Node*q)=p==q!=\null&&tree(q->r)||p!=q&&tree(p->l)&&tree(p->r)&&seg_l(p->l,q)
和
seg_r(Node*p,Node*q)=p==q!=\null&&tree(q->l)||p!=q&&tree(p->l)&&tree(p->r->l)&&seg_r(p->r,q)
为例说明上述步骤(b3)的过程:
先是以seg_l为例:
参见图6,先获取谓词中迭代的指针参数的域,取得seg_l(Node*p,Node*q)的p的迭代域为l和r,q的迭代域为r。
参见图7,对该自引用的节点上的其他谓词引用,根据节点对应的谓词形参,获得其他谓词下的迭代的域和所有域引用,将其加入对应形参一次域引用的所有域引用,取得seg_l(Node*p,Node*q)的p的一次域引用l和r的所有域引用均为l和r,q无。
获得各个形参一次域引用的所有域引用后,对每个形参在当前谓词所有分支上查找一次域引用再用所有域引用递归查找(在碰到自引用节点时,查找还会借由谓词引用递归查找),查找到的节点检查有无别的形参直接指向,所有直接指向这些节点的形参补充所有域引用到迭代的域。
参见图8,先对seg_l一次域引用l的所有域引用递归查找,查找到的节点标记见图9,故seg_l的q需要补充迭代域l;
参见图10,再对seg_l一次域引用r的所有域引用递归查找,,没有需要补充的迭代域。
再以seg_r为例:
参见图11,先获取谓词中迭代的指针参数的域,取得seg_r(Node*p,Node*q)的p的迭代域为l和r,q的迭代域为l。
参见图12,对穿过自引用的出边记为一次域引用,所述出边指向的形状描述部分递归获取所有域引用,将所述递归获取的所有域引用记录到该出边对应一次域引用的所有域引用下面,取得seg_r(Node*p,Node*q)的p的一次域引用l的所有域引用为l和r,q无。
参见图13,对seg_r一次域引用l的所有域引用递归查找,查找到的节点标记见图14,故没有需要补充的迭代域。
本发明实施例还提供了用于易变数据结构程序验证的形状图生成装置,包括:
断言种类细化单元,用于细化不同种类易变数据结构断言,并对细化后的断言种类简化断言描述方法;
形状图初步构造单元,用于按照预设优化顺序对不同断言种类进行形状图构造获取程序的初步形状图,所述不同断言种类的构造方法包括细化后的断言种类对应的形状图构造方法;
形状图优化单元,用于基于初步构造的形状图进行修正优化获取精准形状图。
本发明实施例还提供了一种电子设备,所述电子设备包括:
存储器,用于存储可执行指令;
处理器,用于运行所述存储器存储的可执行指令时,实现上述用于易变数据结构程序验证的形状图生成方法。
存储器可包括存储程序区和存储数据区,其中,存储程序区可存储操作系统、至少一个功能所需的应用程序等,其中,操作系统包含各种系统程序,例如框架层、核心库层、驱动层等,用于实现各种基础业务以及处理基于硬件的任务。应用程序可以包含各种应用程序;存储数据区可存储使用过程中所创建的数据等。此外,存储器可以包括高速随机存取存储器,还可以包括非易失性存储器,例如至少一个磁盘存储器件、闪存器件、或其他易失性固态存储器件。
本发明实施例还提供了一种计算机可读存储介质,存储有可执行指令,所述可执行指令被处理器执行时实现上述用于易变数据结构程序验证的形状图生成方法。应该理解,本发明实施例中的各功能模块或单元可以集成在一起形成一个独立的部分,也可以是各个模块单独存在,也可以两个或更多个模块集成形成一个独立的部分。所述功能如果以软件功能模块的形式实现并作为独立的产品销售或使用时,可以存储在一个计算机可读取存储介质中。基于这样的理解,本发明的技术方案本质上或者说对现有技术做出贡献的部分或者该技术方案的部分可以以软件产品的形式体现出来,该计算机软件产品存储在一个存储介质中,包括若干指令用以使得一台计算机设备(可以是个人计算机、服务器、或者网络设备等)执行本发明各个实施例所述方法的全部或部分步骤。而前述的存储介质包括:U盘、移动硬盘、只读存储器(ROM,Read-0nlyMemory)、随机存取存储器(RAM,RandomAccessMemory)、磁碟或者光盘等各种可以存储程序代码的介质。
本发明不局限于上述具体的实施方式,本领域的普通技术人员从上述构思出发,不经过创造性的劳动,所做出的种种变换,均落在本发明的保护范围之内。
- 用于易变数据结构程序验证的形状图生成方法及装置
- 影像对象表现用数据结构、影像对象表现用数据结构生成程序、影像对象表现用数据结构生成方法、影像软件开发装置、图像处理程序、影像处理方法、影像处理装置及记录介质