一种基于图匹配网络的语义类代码克隆检测方法技术

技术编号:34273716 阅读:10 留言:0更新日期:2022-07-24 16:38
本发明专利技术公开了一种基于图匹配网络的语义类代码克隆检测方法,目的是解决语义类克隆检测结果不准确的问题。技术方案是:构建由代码补全模块、代码中间表示提取模块、语义图构建模块、代码向量生成模块和向量相似度计算器构成的代码克隆检测系统;使用语义类代码克隆数据集对代码向量生成模块中的深度学习模型进行训练;使用代码克隆检测系统对待检测代码进行代码补全、提取代码中间表示、构建代码语义图,训练后的代码向量生成模块将代码语义图转化为高维向量,再使用向量相似度计算器判断向量的相似度是否超过阈值以判断待检测代码是否是克隆代码。采用本发明专利技术可完整获取代码语义信息,有效检测语义类代码克隆,且在代码不可编译时仍能进行检测。编译时仍能进行检测。编译时仍能进行检测。

A method of semantic class code clone detection based on graph matching network

【技术实现步骤摘要】
一种基于图匹配网络的语义类代码克隆检测方法


[0001]本专利技术涉及大型软件维护中的克隆检测技术,具体涉及一种基于图匹配网络的代码克隆检测方法。

技术介绍

[0002]随着计算机的发展,计算机软件已经在社会各个领域得到了广泛的应用,在现代社会中扮演着举足轻重的角色,发挥了重要的作用。随着各行各业对软件系统的需求日益扩增,现代软件系统的代码规模逐渐扩大,导致现代软件系统的开发往往需要耗费大量的人力以及时间。为了提高现代软件系统开发人员在软件开发中的效率,开发人员在开发软件过程中往往会复用一些已有的代码。复用代码的方法主要包括从代码仓库中搜索满足需求的代码,对代码简要修改和复制到目标软件系统中、使用成熟的开发框架例如Spring、Tensorflow等、针对具体任务使用前人总结的设计模式。上述方法虽然提高了开发人员的软件开发效率,但也催生了代码克隆现象。代码克隆是指代码仓库中两段相同或相似的代码。根据已有的研究工作显示,代码克隆已经广泛的存在于现代软件系统之中。在Linux操作系统内核中包含27%

35%的代码存在代码克隆,在当前最大的代码仓库Github中,超过70%的代码都存在代码克隆。虽然重复使用已有的代码可以显著提升软件开发人员的开发效率,但是重复使用已有代码也有可能引入潜藏的漏洞,如在复用代码时,为根据上下文对代码进行更改,使得引入预期外的控制流或数据流。因此代码克隆检测尤为重要。利用代码克隆检测,软件维护人员可以根据已知的恶意程序代码或含有漏洞的代码检测在软件中其他可能潜藏的恶意软件代码和含有漏洞的代码。
[0003]根据两段代码的相似程度的不同,一般将代码克隆分为四类。第一类代码克隆指除了注释和空格不同,其他都相同的两段代码。第二类代码克隆指仅仅函数名或变量名不同的两段代码。第三类代码克隆指在保持语法结构不变的基础上,在代码语句上略有增删的两段代码。第四类代码克隆也叫做语义类代码克隆,指语法结构不同,但是代码语义相同的两段代码。针对代码克隆的种类不同,现有主要有基于匹配和基于深度学习的方法检测代码克隆。基于匹配的代码克隆检测方法,主要通过将代码进行一些转换,再根据代码转换之后的表示形式,利用对应的相似比较算法,判断两段代码是否相似。例如Zu Yue等人在ASE2020会议上发表的文章“CCGraph:a PDG

based code clone detector with approximate graph matching(一种利用相似图匹配算法的基于程序依赖图的克隆检测方法,简称CCGRAPH)”,将代码转化为包含其数据流信息和控制流信息的程序依赖图。为了比较两段代码的程序依赖图的相似性,他们使用Weisfeiler

Lehman图核算法来比较两个图的相似性,最后根据两个图的相似性是否超过既定阈值来判断两段代码是否是克隆代码。基于匹配的克隆检测方法速度较快,不需要前期准备工作,并且在前三种类型的代码克隆检测中可以取得较好的准确率和召回率。但是在解决语义类代码克隆问题时,基于匹配的克隆检测方法的准确率和召回率都有显著下降,导致开发人员在查找语义类克隆检测时,仍然需要花费大量的人力物力检查匹配的克隆检测方法的输出结果。基于深度学习的代码
克隆检测方法是使用深度学习模型将代码转化为可以表示其含义的高维向量,通过训练深度学习模型,可以使克隆代码的向量在高维空间之中更近似。在判断一对代码是否是克隆代码时,使用训练好的深度学习模型将他们转化为高维向量,根据代码向量距离判断两段代码是否是克隆代码。例如Hao Yu等人在ICPC2019会议上发表的文章“Neural detection of semantic code clones via tree

based convolution(基于树型卷积的语义代码克隆检测方法,简称TBCCD)”,将代码转化为抽象语法树,然后利用树型卷积模型将代码的抽象语法树转化为向量,最后比较代码向量的相似度判断代码是否为克隆代码。基于深度学习的代码克隆方法可以更有效的理解代码的语义,因此可以有效检测出语义类代码克隆。但是目前的基于深度学习的代码克隆检测方法主要使用以LSTM网络为代表的基于文本的深度学习模型,只学习了代码的文本和语法信息,在准确率和召回率仍有待提高。
[0004]综上,如何提供一种检测语义类代码克隆的方法,更好地挖掘代码中的信息,更好地使用深度学习模型学习代码语义,使得代码克隆检测更准确,是本领域技术人员正在探讨的热点问题。

技术实现思路

[0005]本专利技术要解决的技术问题是针对语义类克隆检测结果不准确,代码语义信息获取不全面问题,提供一种基于图匹配网络的代码克隆检测方法。此方法基于深度学习检测代码克隆的方法框架,抽取代码的数据流控制流信息构建代码语义图,更完整的提取代码语义信息。使用图匹配网络,可以更有效地学习代码语义图的语义信息,进而更准更全地查找语义类代码克隆。
[0006]为解决上述问题,本专利技术的技术方案是:首先构建由代码补全模块、代码中间表示提取模块、语义图构建模块、代码向量生成模块和向量相似度计算器构成的代码克隆检测系统。然后使用语义类代码克隆数据集对代码向量生成模块中的深度学习模型进行训练,调整深度学习网络模型参数。最后使用代码克隆检测系统对用户输入的待检测代码进行代码补全、提取代码中间表示、构建代码语义图,训练后的代码向量生成模块将代码语义图转化为对应的高维向量V1和V2,再使用向量相似度计算器判断向量的相似度是否超过既定阈值。
[0007]本专利技术包含以下步骤:
[0008]第一步,构建代码克隆检测系统。代码克隆检测系统由代码补全模块、代码中间表示提取模块、语义图构建模块、代码向量生成模块和向量相似度计算器构成。
[0009]代码补全模块与代码中间表示提取模块相连,使用JCoffee

1.0工具(见P Gupta等人在ICSME会议上发表的文献“JCoffee:Using Compiler Feedback to Make Partial Code Snippets Compilable”使用编译器反馈来使代码片段可编译,下载地址:https://github.com/piyush69/JCoffee)对输入的代码对C1,C2分别进行补全,得到补全后的代码对C
‘1,C
‘2,使C
‘1,C
‘2可以进行编译,将C
‘1,C
‘2发送给代码中间表示提取模块。
[0010]代码中间表示提取模块与代码补全模块、语义图构建模块相连,将从代码补全模块接收的C
‘1,C
‘2分别进行编译,提取C
‘1,C
‘2编译过程中的代码中间表示,构成代码中间表示对R1,R2。将R1,R2发送给语义图构建模块。
[0011]语义图构建模块与代码中间表示提取模块、代码向量生成模块相连,从代码中间
表示提取模块接收R1,R2,从R1,R2中提取本文档来自技高网
...

【技术保护点】

【技术特征摘要】
1.一种基于图匹配网络的语义类代码克隆检测方法,其特征在于包含以下步骤:第一步,构建代码克隆检测系统,代码克隆检测系统由代码补全模块、代码中间表示提取模块、语义图构建模块、代码向量生成模块和向量相似度计算器构成;代码补全模块与代码中间表示提取模块相连,对输入的代码对C1,C2分别进行补全,得到补全后的代码对C
‘1,C
‘2,将C
‘1,C
‘2发送给代码中间表示提取模块;代码中间表示提取模块与代码补全模块、语义图构建模块相连,将从代码补全模块接收的C
‘1,C
‘2分别进行编译,提取C
‘1,C
‘2编译过程中的代码中间表示,构成代码中间表示对R1,R2;将R1,R2发送给语义图构建模块;语义图构建模块与代码中间表示提取模块、代码向量生成模块相连,从代码中间表示提取模块接收R1,R2,从R1,R2中提取代码的常量、变量、操作符、API、数据流和控制流信息,分别构建表示代码语义的语义图,得到语义图对G1,G2,将G1,G2发送给代码向量生成模块;代码向量生成模块与语义图构建模块、向量相似度计算器相连,从代码向量生成模块接收G1,G2,使用图匹配网络将G1,G2分别映射为高层向量空间中的两个代码向量V1,V2,将V1,V2发送给向量相似度计算器;向量相似度计算器与代码向量生成模块相连,计算V1,V2的向量相似度SIM,根据SIM是否超过设定的阈值来判断V1,V2所表示的代码对C1,C2是否属于语义类代码克隆;第二步,代码补全模块采用代码补全方法对训练集中的代码进行补全:2.1使用BigCloneBench数据集作为训练代码,从BigCloneBench数据集中所有代码对中选择N对代码以及对应的标注作为训练集,N为正整数;2.2令可编译代码集合Data={};2.3令变量n=1;2.4从训练集中抽取第n个代码段CC
n
,判断CC
n
是否可编译,若CC
n
可编译,转2.5,否则转2.6;2.5将CC
n
加入Data中,令n=n+1,转2.9;2.6使用JCoffee

1.0工具补全CC
n
,得到补全后的代码CC

n
,转2.7;2.7判断CC

n
是否可编译,若可编译,转2.8,否则转2.9;2.8将CC

n
加入Data中,令n=n+1,转2.9;2.9若n≥N,令补全后的Data中数据总数M=n,将补全后的Data发送给代码中间表示提取模块,转第三步;否则转2.4;第三步,代码中间表示提取模块从代码补全模块接收可编译代码集合Data,采用代码中间表示提取方法从Data中提取代码中间表示,构建代码中间表示集合IR,方法为:3.1令代码中间表示集合IR={};3.2令变量m=1;3.3从Data中抽取第m个代码CC
m
,若CC
m
为JAVA语言代码,转3.4;若为C语言代码,则转3.5;3.4提取JAVA代码的代码中间表示,方法为:3.4.1使用JavaC编译代码CC
m
,得到二进制文件Class
m
;3.4.2根据二进制文件Class
m
,使用Soot

4.1.0工具提取代码的中间表示R
m
,将R
m
加入IR,令m=m+1,转3.6;
3.5利用LLVM

9.0工具编译代码CC
m
,得到代码CC
m
的中间表示R
m
,将R
m
加入IR,令m=m+1,转3.6;3.6若m>M,将代码中间表示集合IR发送至语义图构建模块,转第四步;若m≤M,转3.3;第四步,语义图构建模块从代码表示提取模块接收代码中间表示集合IR,采用语义图集合构建方法根据IR构建语义图集合SG,方法为:4.1令语义图集合SG={};4.2令变量p=0;4.3从IR中抽取第p个代码中间表示R
p
,从R
p
中提取关键语义表示信息,过滤无用噪音信息,得到关键语义表示信息队列S
p
,S
p
中第k个元素为过滤掉了无用噪音信息的R
p
中的代码,k为正整数,转4.4;4.4语义图构建模块采用语义图构建方法根据S
p
构建语义图G
p
,方法是:4.4.1初始化语义图G
p
为空,即初始化语义图G
p
的节点集合V
p
、数据流边集合E_data
p
和控制流边集合E_contrpl
p
为空;4.4.2语义图构建模块为G
p
的节点集合V
p
添加变量节点,变量节点(var,type,v
var
)为三元组,var为从中提取的变量,type为var的数据类型,v
var
表示此节点类型为变量节点;4.4.3语义图构建模块为G
p
的节点集合V
p
添加语句块标识符节点,语句块标识符节点(marker,v
control
)为二元组,marker是从中提取的语句块标识符,v
control
表示此节点类型为语句块标识符节点;4.4.4语义图构建模块为语义图G
p
添加操作符节点、数据流边和控制流边:首先查找当前语句所属的语句块标识符节点(u,v
control
),u为节点存储的语句块标识符marker,v
control
表示此节点类型为语句块标识符节点;将操作符节点添加到V
p
中,操作符节点包括函数调用节点、运算符节点、取值操作符节点,函数调用节点(method,v
invoke
)为二元组,method为从中提取的调用函数的函数名,v
invoke
表示此节点类型为函数调用节点;运算符节点(op,v
operator
)为二元组,v
operator
表示此节点类型为运算符节点,其中存储的值为op;取值操作符节点(getelem,v
operator
)是二元组,v
operator
表示此节点运算符节点,其中存储的值为取值操作符getelem;当将函数调用节点(method,v
invoke
)添加到V
p
中时,将控制流边添加到G
p
的控制流边集合E_control
p
中,控制流边((u,v
control
),(method,v
invoke
),e
control

flow
)是三元组,表示函数调用节点(method,v
invoke
)属于语句块标识符节点(u,v
control
)所代表的语句块,e
control

flow
表示添加的边的属性为控制流边;在G
p
的数据流边集合E_data
p
中添加两条数据流边,分别为((var
in
,type,v
var
),(method,v
invoke
),e
data

flow
)和((method,v
invoke
),(var
return
,type,v
var
),e
data

flow
),说明数据从变量节点(var
in
,type,v
var
)输入函数调用节点(method,v
invoke
)进行函数调用计算,经过函数调用计算得到的数据从函数调用节点(method,v
invoke
)输出到变量节点(var
return
,type,v
var
),e
data

flow
表示添加的边的属性为数据流边;当将运算符节点添加到V
p
中时,在G
p
的控制流边集合E_control
p
中添加控制流边((u,v
control
),(op,v
operator
),e
control

flow
),表示函数运算符节点(op,v
operator
)属于语句块标识符节点(u,v
control
)所代表的语句块;在G
p
的数据流边集合E_data
p
中以三元组的形式添加两条数据流边,即((var
in
,type,v
var
),(op,v
operator
),e
data

flow
)和((op,v
operator
),(var
return

type,v
var
),e
data

flow
),表示数据从变量节点(var
in
,type,v
var
)输入运算符节点(op,v
operator
),运算后的数据从运算符节点(op,v
operator
)输出到变量节点(var
return
,type,v
var
);当将取值操作符节点加入V
p
中时,在G
p
的控制流边集合E_control
p
中添加控制流边((u,v
control
),(getelem,v
operator
),e
control

flow
),表示取值操作符节点(getelem,v
operator
)属于语句块标识符节点(u,v
control
)所代表的语句块;在G
p
的数据流边集合E_data
p
中以三元组的形式添加两条数据流边,即((var
in
,type,v
var
),(getelem,v
operator
),e
data

flow
),和((getelem,v
operator
),(var
return
,type,v
var
),e
data

flow
),表示数组中的数据从数组变量节点(var
in
,type,v
var
)输入取值操作符节点(getelem,v
operator
),经过取值操作从数组变量中得到的数据从取值操作符节点(getelem,v
operator
)输出到变量节点(var
return
,type,v
var
);当为判断语句或跳转语句时,在G
p
的控制流边集合E_control
p
中以三元组的形式添加控制流边((u,v
control
),(newmarker,v
control
),e
control

flowr
),表示程序执行时将从当前语句块标识符节点(u,v
control
)所代表的语句块跳转到语句块标识符节点(newmarker,v
control
)所代表的语句块;在G
p
的数据流边集合E_data
p
中以三元组的形式添加数据流边((var
in
,type,v
var
),(var
return
,type,v
var
),e
data

flow
),说明数据从变量var
in
输出到变量var
return
中;将G
p
加入语义图集合SG中;4.5若p大于代码中间表示数据集IR的大小,则得到语义图集合SG,转第五步;否则令p=p+1,转4.3;第五步,根据语义图集合SG制作代码向量生成模块所需的训练数据集TrainingSet,TrainingSet中的第i个元素为三元组将TrainingSet发送到代码向量生成模块;Label
i
为True,表示和所对应的代码功能相同,为克隆代码;Label
i
为False,表示和所对应的代码不为克隆代码;第六步:采用TrainingSet训练代码向量生成模块,得到表示语义图信息的图匹配网络,方法是:6.1设置训练图匹配网络所需参数;方法是:6.1.1设置图匹配网络包含网络层数T=4;6.1.2设置图匹配网络学习率ir=0.001;6.1.3设置训练轮数num_epochs=50;6.1.4初始化训练轮数epochs=0;6.2令变量i=1;6.3从训练数据集TrainingSet中抽取第i个数据D
i
,6.4采用第一初始化方法初始化中节点的向量值与边的权重值,得到初始化后的第一语义图方法如下:6.4.1使用Word2vec模型初始化中节点的向量值:从的节点集合V
i1
中顺序选择节点x,x∈V
i1
,将节点x中存储的内容输入Word2vec模型,将Word2vec模型输出值作为节点x的初始化向量6.4.2令的数据流边集合中每条边的权重值为1;
6.4.3令的控制流边集合中每条边的权重值为

1;6.5采用第二初始化方法初始化中节点的向量值与边的权重值,得到初始化后的第二语义图方法如下:6.5.1使用Word2vec模型初始化中节点的向量值,从的节点集合V
i2
中顺序选择节点z,z∈V
i2
,将节点z中存储的内容输入Word2vec模型,将Word2vec模型输出值作为节点z的初始化向量6.5.2令的数据流边集合中每条边的权重值为1;6.5.3令的控制流边集合中每条边的权重值为

1;6.6采用迭代更新方法更新第一语义图中各节点的向量表示,得到第一最终语义图迭代更新方法如下:6.6.1初始化变量t=1;6.6.2从的节点集合V
i1
中顺序选择第一节点x,若的节点集合V
i1
中所有节点都已被选择,则转6.6.7;否则转6.6.3;6.6.3计算在第t次迭代时,中的节点与的相似性,方法是:6.6.3.1从的节点集合V
i2
中顺序选择第二节点,令第二节点为z,若的节点集合V
i2
中所有节点都已被选择,则转6.6.3.3;否则转6.6.3.2;6.6.3.2计算x与z的相似度α
z

x
,其中指x在t

1次迭代后的向量表示,指z在t

1次迭代后的向量表示,指中任意一个不是z的节点在t

1次迭代后的向量表示,转到6.6.3.1;6.6.3.3计算在第t次迭代时x与的节点集合V
i2
中所有节点的相似度和中所有节点的相似度和6.6.4计算在第t次迭代时,第一语义图中与x有边相连的其它节点即所有第三节点y传递给x的消息向量和m
y

x
为中y对x的消息向量;6.6.5更新中x在第t次迭代后的向量表示其中GRU表示门控循环神经网络,表示利用门控循环神经网络根据第t

1次迭代后x节点的向量生成第t次迭代后的向量表示6.6.6令t=t+1;若t小于T,转6.6.2;否则说明迭代更新完毕,得到第一最终语义图转6.7;6.7采用6.6所述迭代更新方法更新中各节点的向量表示,得到第二最终语义图6.8计算的向量表示其中MLP为多层感知器模型,表示
利用多层感知器模型将中所有节点的向量汇总为向量V
i1
,其中为经过T轮迭代后得到的最终语义图中各个节点的向量值;6.9计算的向量表示V
i2
,6...

【专利技术属性】
技术研发人员:李姗姗薛志鹏余跃姜志杰董威陈振邦陈立前徐如林周海芳
申请(专利权)人:中国人民解放军国防科技大学
类型:发明
国别省市:

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

1