1.本发明涉及代码克隆检测技术领域,具体涉及一种代码克隆检测方法及系统。
背景技术:2.随着代码托管平台和开源社区的发展,网络上各种开源项目越来越多样化并且获取也更加便利。代码常在多个软件系统中复制、传播和演化,给软件系统带来了软件质量的不确定性和风险,甚至导致漏洞的传播。近年来,代码克隆检测已经成为软件工程领域一个越来越重要的课题。按照克隆的程度,代码克隆可以分为type-1(完全克隆)、type-2(重命名克隆)、type-3(增删改克隆)、type-4(自实现克隆)四大类。
3.随着深度学习的发展,许多神经网络模型也被应用到代码克隆检测领域。目前基于深度学习的代码克隆检测根据其使用的代码中间形式可以大致分为基于纯文本、基于词法token、基于树、基于图的检测四类。在基于树的代码克隆检测方法中,常见的方法之一是将源代码解析成抽象语法树作进一步的处理并用于克隆检测。其中的抽象语法树(abstract syntax tree,ast)是源代码语法结构的一种抽象表现形式,它是编译源代码产生的一个中间结果,以树的形式包含了源代码中的语法信息。最近的代码克隆检测研究表明,基于抽象语法树的方法比其他方法能更好地表示源代码。但基于抽象语法树的的代码克隆检测技术目前仍存在如下几点局限性:
4.(1)检测效率问题:基于抽象语法树的代码克隆检测技术需要构建抽象语法树,然后使用树匹配算法搜索结构相似的树,并将这些相似树所对应的代码作为克隆代码返回。但现有技术在下一次检测过程中仍需要再次对代码库中的代码执行构建抽象语法树的操作,这一过程需要消耗时间和空间成本,导致执行效率较低。
5.(2)梯度消失问题:与自然语言处理中的长文本类似,当抽象语法树很深时,以树为基础的神经网络模型会容易受到梯度消失的影响,权重无法更新,导致模型训练失败。
6.(3)检测准确率问题:基于深度学习的代码克隆检测技术在匹配检测过程中大多基于孪生模型,其局限性在于,它们直接对比两个抽象语法树,不考虑是否存在细粒度上的相似结构,检测粒度过于粗糙,导致原本可能判断为相似的两个代码片段在粗粒度上直接判断为不相似,从而导致检测准确率不高,容易出现漏报误报现象。
技术实现要素:7.有鉴于此,本发明提供了一种代码克隆检测方法及系统,能够高效、准确地完成代码克隆检测。
8.本发明采用的具体技术方案如下:
9.一种代码克隆检测方法,包括:
10.步骤一:根据代码片段生成抽象语法树ast,遍历所述ast,获得多条ast路径组成的与所述代码片段对应的ast路径组;
11.步骤二:将所述ast路径组中的每条ast路径转换成对应的词向量l,多个词向量l
组成所述ast路径组对应的语义向量l;
12.步骤三:扫描代码托管平台上的代码片段,重复步骤一、二,得到语义向量集∪l;
13.步骤四:将待测目标代码片段通过步骤一、二,得到对应的语义向量l1;
14.步骤五:将待测目标代码片段转换成的语义向量l1与语义向量集∪l中的任意一个语义向量l2组成语义向量表示对(l1,l2);利用比较聚合模型对所述语义向量表示对(l1,l2)进行处理,得到处理后的向量表示对(l
′1,l2),根据所述向量表示对(l
′1,l2),计算向量l
′1与l2的相似度s;
15.步骤六:遍历所述语义向量集∪l,重复步骤五,选出代码托管平台上具有相似度最大值的语义向量对应的代码片段,根据预设阈值判断所述目标代码片段和所述相似度最大值对应的代码片段是否存在克隆关系。
16.进一步地,所述根据代码片段生成抽象语法树ast,遍历所述ast,获得多条ast路径组成的与所述代码片段对应的ast路径组,包括:
17.根据所述代码片段采用代码解析工具生成抽象语法树ast,采用深度优先遍历算法遍历所述ast,获得多条ast路径组成与所述代码片段对应的ast路径组。
18.进一步地,所述利用比较聚合模型对所述语义向量表示对(l1,l2)进行处理,包括:
19.所述比较聚合模型的对齐层对所述语义向量表示对(l1,l2)进行路径匹配,针对所述语义向量l1中的每个词向量l
1i
,通过与语义向量l2的细粒度ast路径信息加权,得到更新词向量l
′
1i
;
20.所述比较聚合模型的比较层将所述语义向量l1中的每个词向量l
1i
与所述更新词向量l
′
1i
进行比较拼接,获得新的向量l
1,i
;
21.所述比较聚合模型的聚合层对所述新的向量l
1,i
进行聚合特征提取,得到降维之后的l
′1,并将l
′1与语义向量集中的语义向量l2组成新的向量表示对(l
′1,l2)。
22.进一步地,所述比较聚合模型的对齐层对所述语义向量表示对(l1,l2)进行路径匹配,包括:
23.计算所述语义向量l1中的词向量l
1i
与语义向量l2中的词向量l
2j
的相似度,获得注意力矩阵e
ij
;
24.对所述注意力矩阵e
ij
进行归一化处理获得注意力概率系数α
ij
;
25.根据所述注意力概率系数α
ij
,对所述语义向量l1中的词向量l
1i
进行加权求和获得所述更新词向量l
′
1i
。
26.进一步地,所述根据处理后的所述向量表示对(l
′1,l2),计算向量l
′1与l2的相似度s,包括:
27.计算处理后的语义向量l
′1与语义向量集中的语义向量l2的向量距离d,通过函数映射将所述向量距离d映射到0~1之间,获得向量l
′1与语义向量l2对应代码片段的相似度s。
28.进一步地,在将所述待测目标代码片段转换成语义向量l1之后,还包括:
29.将所述语义向量l1补充存储至所述语义向量集∪l。
30.进一步地,所述将所述ast路径组中的每条ast路径转换成对应的词向量l,包括:
31.采用词嵌入模型将每条所述ast路径转换成对应的词向量l。
32.一种代码克隆检测系统,包括:
33.代码预处理模块,用于根据代码片段生成抽象语法树ast,遍历所述ast,获得多条ast路径组成的与所述代码片段对应的ast路径组;并将所述ast路径组中的每条ast路径转换成对应的词向量l,多个词向量l组成所述ast路径组对应的语义向量l;扫描代码托管平台上的代码片段,得到语义向量集∪l;
34.语义向量生成模块,用于将待检测的目标代码片段转换成对应的语义向量l1,并将所述语义向量l1发送至克隆检测模块;
35.克隆检测模块,用于将所述语义向量l1与所述语义向量集∪l的任意一个语义向量l2组成语义向量表示对(l1,l2),并利用比较聚合模型对所述语义向量表示对(l1,l2)进行处理,根据处理后的所述向量表示对(l1,l2)计算两个向量间的相似度,遍历所述语义向量集∪l,选出代码托管平台上具有相似度最大值的代码片段,根据预设阈值判断所述目标代码片段和所述相似度最大值对应的代码片段是否存在克隆关系。
36.进一步地,在所述代码预处理模块中,
37.根据所述代码片段采用代码解析工具生成抽象语法树ast,采用深度优先遍历算法遍历所述ast,获得多条ast路径组成与所述代码片段对应的ast路径组。
38.进一步地,在所述克隆检测模块中,所述利用比较聚合模型对所述语义向量表示对(l1,l2)进行处理,包括:
39.所述比较聚合模型的对齐层对所述语义向量表示对(l1,l2)进行路径匹配,针对所述语义向量l1中的每个词向量l
1i
,通过与语义向量l2的细粒度ast路径信息加权,得到更新后的词向量l
′
1i
;
40.所述比较聚合模型的比较层将所述语义向量l1中的每个词向量l
1i
与所述更新词向量l
′
1i
进行比较拼接,获得新的向量l
1,i
;
41.所述比较聚合模型的聚合层对所述新的向量l
1,i
进行聚合特征提取,得到降维之后的l
′1,并将l
′1与语义向量集中的语义向量l2组成新的向量表示对(l
′1,l2)。
42.有益效果:
43.(1)一种代码克隆检测方法,根据代码生成抽象语法树ast,遍历ast,获得多条ast路径,组成ast路径组,解决了抽象语法树很深导致梯度消失的问题;扫描代码托管平台,将源代码对应的ast路径组中的每条ast路径转换成词向量,多个词向量组成ast路径组对应的语义向量,得到多个语义向量构成语义向量集,语义向量集在每次检测过程中不必重复生成,从而节省时间开销,提高检测的执行效率。
44.(2)利用比较聚合模型对语义向量表示对进行处理,首先对细粒度的ast路径进行路径匹配,将匹配结果加权得到带权重的更新词向量,然后通过聚合提取细粒度特征并反映到待测目标代码片段,最后与语义向集中的语义向量逐一进行相似性检测,获得最终检测结果。检测过程中提取了细粒度ast路径信息,其性能优于孪生网络模型,解决了传统方法采用孪生网络模型检测准确率不高的问题。
45.(3)通过预先构建语义向量集,并不断将根据待测目标代码片段获得的语义向量补充更新至语义向量集,在后续的克隆检测过程中,可以直接使用构建好的语义向量集,进一步提高了检测速度和克隆检测效率。
附图说明
46.图1是本发明的代码克隆检测系统框架图;
47.图2是代码预处理的流程图;
48.图3是示例代码对应生成的抽象语法树;
49.图4是示例代码对应的ast路径;
50.图5是待测目标代码片段对应的语义向量生成的流程图;
51.图6是克隆检测模块进行克隆检测的流程图;
52.图7是比较聚合模型的框架图。
具体实施方式
53.本发明提供了一种代码克隆检测方法及系统,根据代码生成抽象语法树ast,遍历ast,获得多条ast路径,组成ast路径组,解决了抽象语法树很深导致梯度消失的问题;遍历代码托管平台,将源代码对应的ast路径组中的每条ast路径转换成词向量,多个词向量组成ast路径组对应的语义向量,得到多个语义向量构成语义向量集,语义向量集在每次检测过程中不必重复生成,从而提高了执行效率。
54.利用比较聚合模型对语义向量表示对进行处理,先对细粒度的ast路径进行路径匹配,将匹配结果加权得到带权重的更新词向量,然后通过聚合提取细粒度特征并反映到待测目标代码片段,最后与语义向量集中的语义向量逐一进行相似性检测,获得最终检测结果。检测过程中提取了细粒度ast路径信息,其性能优于孪生网络模型,解决了传统方法采用孪生网络模型检测准确率不高的问题。
55.随着代码托管平台和开源社区的发展,越来越多的开发者选择将代码上传到代码托管平台,便于代码团队之间的交流与合作。同时开发人员为提高软件开发效率,通常会复用已有的软件资源,代码在多个软件中复制、传播和演化,给软件系统带来了软件质量的不确定性和风险,甚至导致漏洞的传播,难以保证准确性。如果不能及时控制代码克隆的增长,则管理和维护代码托管平台的行为将增加人工成本,并导致软件维护成本增加。由于人工检测代码克隆效率低、成本高,难以保证准确性,因此,如何自动、准确、快速地对代码托管平台上的海量代码克隆进行检测是当前研究的核心问题。
56.为了解决这个问题,研究人员提出代码克隆检测技术,旨在自动化定位软件系统中的克隆代码,节省成本,降低出错风险。典型的代码克隆检测可以分为以下几个步骤:首先对源代码进行预处理和规范化,得到适当的源代码中间表示,例如文本代码表征或者抽象语法树;然后通过匹配检测将代码片段两两对比,得到代码克隆对;再进行筛选分类等后处理操作,过滤假阳性代码克隆;最后通过将克隆对聚合为克隆类,生成检测结果。
57.随着深度学习在各种领域取得巨大成果,如何使用深度学习技术进行代码克隆检测也成为了最新的研究方向。基于深度学习的代码克隆检测技术利用大规模数据训练判断代码克隆的分类器,相比传统的代码克隆检测技术,能够更好地挖掘出大量数据中的隐藏模式,获得有效的特征表达,从而取得更好的克隆检测性能。根据使用代码中间表示形式的不同,基于深度学习的代码克隆检测技术大致可以分为:基于文本的方法,基于词法分析的方法,基于树的方法,基于图的方法。
58.基于文本的代码克隆检测方法通常将代码视为自然语言文本进行处理,利用文本
相似性判断代码的相似程度。由于它通常直接在源代码上进行相似性判断,不用对代码进行转化等操作,因此具有较快的检测速度,但其通常仅对简单的复制粘贴行为具有良好的检测效果。在基于词法分析的代码克隆检测方法中,所有源代码行在编译器的词法分析阶段被划分为一系列词法单元token,然后比较token序列中的相同token,如果相同token所占的比例超过阈值,则判定为克隆。与基于文本的代码克隆检测技术相比,基于词法分析的代码克隆检测技术对格式变化、标识符重命名等产生的克隆代码具有更好的检测效果。基于树的代码克隆检测技术是将源代码转化为解析树或抽象语法树来进行表达,之后利用树匹配算法搜索相似的子树。当找到相似的子树时,相似的子树对应的代码片段会以克隆对的形式返回。基于图的代码克隆检测方法通过静态程序分析技术抽取语义关系图结构,通过图相似度匹配来进一步理解代码语义之间的相似性,因此相较于基于文本、词法分析和语法分析的检测技术能够挖掘更深层次的克隆代码,但是由于图的计算复杂度很高,并且检测复杂度随代码的长度增加而增大,因此,基于对上述方法的总结比较,本发明选择基于树的优化方法进行代码克隆检测。
59.现有技术中,使用抽象语法树作为代码中间表示的方法有基于树的卷积神经网络(tree-based convolutional neural network,tbcnn)和基于树的长短时记忆网络(tree-structured long short-term memory networks,tree-lstm),tcbnn针对程序的抽象语法树结构,利用滑动窗口机制来编码抽象语法树,从而捕获程序的结构信息。tree-lstm自下而上的遍历和编码抽象语法树来捕获程序的结构信息。但两者直接编码整个抽象语法树,可能会存在梯度消失问题。
60.针对梯度消失问题,基于抽象语法树的神经网络模型(abstract syntax tree-based neural network,astnn)将每个大ast树分割成一系列小的语句树,通过捕获语句的词汇和句法知识,将语句树编码为向量。基于语句向量序列,采用双向循环神经网络(recurrent neural network,rnn)模型最终生成代码片段的向量表示。但astnn用语句子树序列表现程序,对长程序上下文中的词序不敏感,因此可能会出现信息损失的现象。同时双向rnn模型在训练过程中可能会发生梯度消失问题,权重无法被更新,最终导致训练失败。
61.同样的,基于哈希学习的克隆检测(clone detection with learning to hash,cdlh)是一种基于深度学习的检测方法,利用word2vec来捕获文本信息,然后利用长短时间记忆网络(long short-term memory,lstm)模型训练抽象语法树ast。该方法虽然利用ast得到了结构信息,但是需要将ast树转化为二叉树,改变了树的语法结构,导致树过深,出现长期依赖丢失、梯度爆炸等问题。
62.基于抽象语法树的代码克隆检测技术目前存在如下几点局限性:
63.(1)检测效率问题:基于抽象语法树的代码克隆检测技术需要构建抽象语法树,然后使用树匹配算法搜索结构相似的树,并将这些相似树所对应的代码作为克隆代码返回。但现有技术在下一次检测过程中仍需要再次对代码库中的代码执行构建抽象语法树的操作,这一过程需要消耗时间和空间成本,导致执行效率较低。
64.(2)梯度消失问题:与自然语言处理中的长文本类似,当抽象语法树很深时,以树为基础的神经网络模型会容易受到梯度消失的影响,权重无法更新,导致模型训练失败。
65.(3)检测准确率问题:基于深度学习的代码克隆检测技术在匹配检测过程中大多
基于孪生模型,其局限性在于,它们通常直接对比两个抽象语法树,不考虑是否存在细粒度上的相似结构,检测粒度过于粗糙,导致原本可能判断为相似的两个代码片段在粗粒度上直接判断为不相似,从而导致检测准确率不高,容易出现漏报误报现象。
66.针对上述不足,本发明提出了一个基于代码托管平台的代码克隆检测方法,具体改进包括:
67.针对局限性(1),本发明预先生成一个语义向量集,基于代码托管平台搜集代码库,对其中的源代码生成抽象语法树(ast),遍历抽象语法树生成一组ast路径,通过词嵌入模型完成单个ast路径对应的词向量表示,多个词向量组成ast路径组对应的语义向量,最后保留得到语义向量集,后续在对代码进行克隆检测的过程中可以直接使用预先生成的语义向量集进行基于比较聚合模型的克隆检测,提高检测速度,节省时间开销,提高执行效率。
68.针对局限性(2),本发明将抽象语法树分解为一组ast路径,通过词嵌入模型将一组ast路径生成对应的语义向量,以此作为抽象语法树的表示。这种细粒度的处理使得模型可以很好处理很深的抽象语法树,解决梯度消失问题;另一方面,在后续克隆检测中,这种将抽象语法树分解为ast路径的处理可以减少漏报误报现象,提高检测准确率。
69.针对局限性(3),本发明基于深度学习,提出了一种基于比较聚合模型的代码克隆检测模型,首先对细粒度的ast路径进行相似度匹配,匹配结果加权得到带权重更新的词向量,最后通过聚合将细粒度特征反映到整个代码片段,进行最终的相似性检测,其性能优于孪生网络模型。
70.下面结合附图并举实施例,对本发明进行详细描述。
71.首先对本发明实施例中的技术用语进行解释:
72.代码托管平台:代码托管平台提供了分享开源项目的平台,为开发团队提供了存储、分享、发布和合作开发项目的中心化云存储场所。常见的平台有:github、gitlib、码云gitee。
73.代码克隆:代码克隆是指存在于代码库中两个及两个以上相同或者相似的代码片段,是软件开发的常见现象。造成这种现象的主要原因是软件开发者为了提高效率通过复制粘贴或进行修改来复用代码片段。通常情况下,代码克隆关注在文本、语法或功能上相似的代码片段,并通过克隆对的形式对表现出克隆的代码进行标示。
74.代码克隆类型:根据克隆的程度可以将代码克隆分为四种类型:(l)type-l(完全克隆)除空格、格式和注释外,是完全相同的代码片段;(2)type-2(重命名克隆)在type-1的基础上,除标识符、常量、类型外,在语法或结构上相同的代码段;(3)type-3(增删改克隆)在type-2的基础上,改变、增加或删除代码中的少量语句,是语法结构相似的代码片段。(4)type-4(自实现克隆)两个代码片段实现的功能相同,但实现方法不同。
75.代码片段:代码片段f指代码文件中的某个连续区可以通过三元组(f,s,e)定位标识,包括代码文件名f、代码片段的起始行号s以及终止行号e。通常包括若干有含义的语句,可以是类、函数、有开始结束标识的代码块或者一个声明的序列。
76.代码克隆对:代码克隆对是指一对相似的代码片段,由三元组表示,包括彼此相似的代码片段f1和f2,以及它们的克隆类型
77.代码克隆类:代码克隆类是指一组相似的代码片段,由元组指定其中每对不同片段都是克隆对这些克隆对之间有一定的关联,且关联是对称且对等的。
78.代码克隆检测:代码克隆检测是指通过一定的技术方法自动化定位代码之间相似的克隆代码片段。目前常见的基于深度学习的代码克隆检测方法主要分为四类:基于纯文本的克隆检测、基于词法的克隆检测、基于树的克隆检测、基于图的克隆检测。
79.抽象语法树ast路径:遍历抽象语法树ast,从根节点出发到叶节点结束的一条ast路径。
80.词向量:单个ast路径的向量表示。利用词嵌入模型将一条ast路径映射到向量空间中,得到对应的向量表示,用l表示。
81.语义向量:抽象语法树ast的向量表示,由一组ast路径组成,用l=(l1,l2,...,ln)表示,其中li,i=(1,2,...,n)为单个ast路径的向量表示。
82.语义向量集:多个语义向量的集合,用∪l表示,其中∪表示并集。基于代码托管平台上的代码片段,生成抽象语法树ast对应的语义向量的集合。
83.本发明实施例提供了一种代码克隆检测方法,包括如下步骤:
84.步骤一、根据代码片段生成抽象语法树ast,遍历ast,获得多条ast路径组成的与代码片段对应的ast路径组;
85.在一具体实施例中,根据代码片段采用代码解析工具生成抽象语法树ast,采用深度优先遍历算法遍历ast,获得多条ast路径组成与代码片段对应的ast路径组。
86.步骤二、将ast路径组中的每条ast路径转换成对应的词向量l,多个词向量l组成ast路径组对应的语义向量l;
87.在一具体实施例中,采用词嵌入模型将每条ast路径转换成对应的词向量l。
88.步骤三、扫描代码托管平台上的代码片段,重复步骤一、二,得到语义向量集∪l;
89.在一具体实施例中,扫描代码托管平台上的代码库,获得其中的代码片段对应的ast路径组,将每个ast路径组转换为对应的语义向量l,最后得到语义向量集∪l。
90.步骤四:待测目标代码片段通过步骤一、二,得到对应的语义向量l1;
91.在一具体实施例中,开发人员上传待测目标代码,生成抽象语法树ast,遍历得到ast路径,单个ast路径转换为对应的词向量l,多个词向量l组成ast路径组对应的语义向量l1。
92.步骤五、将由待检测的目标代码片段转换成的语义向量l1与语义向量集∪l中的任意一个语义向量l2组成语义向量表示对(l1,l2);利用比较聚合模型对语义向量表示对(l1,l2)进行处理得到处理后的向量表示对(l
′1,l2),根据所述向量表示对(l
′1,l2)计算相似度s即向量l
′1与l2的相似度;
93.在一具体实施例中,在将目标代码片段转换成语义向量l1之后,将语义向量l1补充存储至语义向量集∪l。
94.在一具体实施例中,利用比较聚合模型对语义向量表示对(l1,l2)进行处理,包括以下步骤:
95.步骤1、比较聚合模型的对齐层对语义向量表示对(l1,l2)进行路径匹配,针对所述
语义向量l1中的每个词向量l
1i
,通过与语义向量l2的细粒度ast路径信息加权,得到更新后的词向量l
′
1i
;
96.在一具体实施例中,首先计算语义向量l1中的词向量l
1i
与语义向量l2中的词向量l
2j
的相似度,获得注意力矩阵e
ij
;之后,对注意力矩阵e
ij
进行归一化处理获得注意力概率系数α
ij
;最后,根据注意力概率系数α
ij
,对词向量l
1i
进行加权求和获得词向量l
′
1i
。
97.步骤2、比较聚合模型的比较层将语义向量l1中的每个词向量l
1i
与更新词向量l
′
1i
进行比较拼接,学习l
1i
和l
′
1i
的关联关系,得到新的向量l
1,i
。
98.经过比较拼接,学习到的向量l
1,i
维度相较于l
1i
、l
′
1i
增加,为了降低计算复杂度,引入聚合层进行降维操作。
99.步骤3、比较聚合模型的聚合层对新的向量l
1,i
进行聚合特征提取,得到降维之后的l
′1,并将l
′1与语义向量集中的语义向量l2组成新的向量表示对(l
′1,l2)。
100.在一具体实施例中,根据处理后的向量表示对(l
′1,l2)计算相似度s,包括:
101.计算处理后的语义向量l
′1与语义向量集中的语义向量l2的向量距离d,通过函数映射将向量距离d映射到0~1之间,获得目标代码片段与当前源代码片段的相似度s;
102.步骤六、遍历语义向量集∪l,重复步骤五,选出代码托管平台上具有相似度最大值的代码片段,根据预设阈值判断目标代码片段和相似度最大值对应的代码片段是否存在克隆关系。
103.在实际实施过程中,将向量表示对的相似度从大到小排序,确定代码托管平台上具有最大相似度的代码片段,根据预设阈值判断所述目标代码片段和所述最大相似度代码片段是否存在克隆关系。
104.本发明实施例还提供了一种代码克隆检测系统,图1是本发明的代码克隆检测系统框架图,如图1所示,包括:
105.代码预处理模块,用于根据代码片段生成抽象语法树ast,遍历ast,获得多条ast路径组成的与代码片段对应的ast路径组;并将ast路径组中的每条ast路径转换成对应的词向量l,多个词向量l组成ast路径组对应的语义向量l;扫描代码托管平台上的代码,得到语义向量集∪l;
106.在一具体实施例中,在代码预处理模块中,根据代码片段采用代码解析工具生成抽象语法树ast,采用深度优先遍历算法遍历ast,获得多条ast路径组成与代码片段对应的ast路径组。遍历代码托管平台,多个语义向量组成语义向量集∪l。
107.语义向量生成模块,用于将待检测的目标代码片段转换成语义向量l1,并将语义向量l1发送至克隆检测模块。
108.克隆检测模块,用于遍历语义向量集∪l,选出代码托管平台上具有相似度最大值的代码片段,根据预设阈值判断所述目标代码片段和相似度最大值对应的代码片段是否存在克隆关系。具体地,将语义向量l1与语义向量集∪l中的任意一个语义向量l2组成语义向量表示对(l1,l2),并利用比较聚合模型对语义向量表示对(l1,l2)进行处理得到处理后的向量表示对(l
′1,l2),根据所述向量表示对(l
′1,l2)计算相似度s。。
109.在一具体实施例中,在克隆检测模块中,利用比较聚合模型对语义向量表示对(l1,l2)进行处理,包括:
110.比较聚合模型的对齐层对语义向量表示对(l1,l2)进行路径匹配,针对所述语义向
量l1中的每个词向量l
1i
,通过与语义向量l2的细粒度ast路径信息加权,得到更新后的词向量l
′
1i
;
111.比较聚合模型的比较层将语义向量l1中的每个词向量l
1i
与更新词向量l
′
1i
进行比较拼接,获得新的向量l
1,i
;
112.比较聚合模型的聚合层对新的向量l
1,i
进行聚合特征提取,得到降维之后的l
′1,并将l
′1与语义向量集中的语义向量l2组成新的向量表示对(l
′1,l2)。
113.在上述代码克隆检测系统的各个模块中,具体执行步骤和方法可以参照上述代码克隆检测方法中的步骤,这里不再赘述。
114.本发明实施例提供的代码克隆检测系统,代码预处理主要完成的任务是遍历托管平台上的语料库,利用代码解析工具生成抽象语法树,然后将其分解为一组ast路径,并输入词嵌入模型得到ast路径组对应的语义向量,遍历结束后存储为语义向量集。
115.当开发人员上传目标代码提出克隆检测需求后,根据框架图中下半部分进行语义向量生成、克隆检测两部分的处理:首先将开发人员上传的目标代码片段经过抽象语法树生成语义向量;然后基于比较聚合模型,通过对齐、比较、聚合三层对待测目标代码片段语义向量与语义向量集中的语义向量逐一组成的语义向量表示对进行处理,得到两者的相似度,最后根据代码相似度大小排序,完成克隆检测。语义向量生成步骤生成的语义向量可以补充到语义向量集中,实现语义向量集的增量更新。
116.为了使得本领域的技术人员更好地理解本发明的技术方案,下面结合具体的场景实施例对本发明的技术方案进行阐述。
117.场景实施例
118.在本场景实施例中,对各个步骤的具体过程进行了介绍,同时对用到的具体函数和计算进行了举例说明。
119.(1)代码预处理
120.代码预处理是本发明代码克隆检测方法的基础,可以视为整个克隆检测过程的准备工作。其主要工作是遍历托管平台上的源码语料库,生成对应的语义向量,多个语义向量组生成一个语义向量集并对语义向量集进行存储。而在下一次检测过程中不需要再次对托管平台上的代码执行构建抽象语法树操作,可以直接使用语义向量集进行克隆检测,从而克服了现有检测执行效率较低的局限性,大大减少了克隆检测的时间,提高了克隆检测的效率。
121.在语义向量生成步骤中,开发人员上传代码生成的语义向量补充到语义向量集中,实现语义向量集的增量更新,扩大后续代码的检测面,提高克隆检测的准确率。
122.图2是代码预处理的流程图,如图2所示,主要包括以下步骤:
123.步骤一:抽取源码:扫描基于托管平台上的源码语料库,抽取源码。
124.步骤二:生成抽象语法树:使用代码解析工具包括但不限于antlr工具,生成代码对应的抽象语法树(ast)。为了更好的理解,下面给出示例代码片段生成抽象语法树的解析过程:
125.function add(a,b){
126.return a+b;
127.}
128.上述示例代码片段是一个简单的函数定义对象,id名字为add,两个参数a和b,一个块状域对象(body),即大括号内部的内容。名字add是一个最基础的标志(identifier)对象,用来作为函数的唯一标志,不能进一步解析,body进一步解析为return域对象,继续打开为二项式对象,最后拆解为标志对象a、运算符+和标志对象b,解析结束。图3是示例代码对应生成的抽象语法树。
129.步骤三:遍历抽象语法树生成一组ast路径。这里一条ast路径是指抽象语法树中从根节点出发,到叶节点结束的一条路径。遍历一棵抽象语法树得到所有的路径组合为一组ast路径。
130.树的遍历算法有很多,本场景实施例使用深度优先遍历算法作为示例,图4是示例代码对应的ast路径,如图4所示,其中为了更好的描述,图4左侧表示将图3的抽象语法树每个节点编号,对应的ast路径展示在图4的右侧。
131.步骤四:生成ast路径组对应的语义向量:通过词嵌入模型将一组ast路径转换为计算机可识别的向量表示,从而便于后续的进一步处理。目前流行的基于神经网络进行词嵌入的语言模型有很多,包括但不限于word2vec模型,其本质是将ast路径组的每一个ast路径映射到一个向量上,由此产生的词向量包含了丰富的上下文语义。定义待测目标代码片段f的ast路径组对应的语义向量用l=(l1,l2,...,ln)表示,其中li,i=(1,2...n)为单个ast路径的向量表示。
132.上述四个步骤进行完毕后,继续扫描托管平台上的源代码语料库,重复四步操作。待扫描结束后,将第四步生成的多组ast路径对应的语义向量保存,生成语义向量集∪l。
133.(2)待测目标代码片段对应语义向量生成
134.语义向量生成的主要工作是将开发人员上传的待测目标代码片段转化为对应的语义向量,具体的方法与代码预处理的四个步骤大致相同,这里不详细描述。图5是待测目标代码片段对应的语义向量生成的流程图,如图5所示,主要包括以下步骤:
135.步骤一:开发人员提供代码片段;
136.步骤二:生成抽象语法树,这里同样使用代码解析工具;
137.步骤三:遍历抽象语法树生成一组ast路径;
138.步骤四:生成ast路径组对应的语义向量,利用词嵌入模型得到一组ast路径组对应的语义向量,用l1表示。
139.(3)克隆检测
140.克隆检测的核心任务是判断开发人员上传的目标代码片段是否在托管平台上存在对应的相似片段,其输入是目标代码片段的语义向量,同时依据代码预处理步骤生成的语义向量集,输出检测结果。图6是克隆检测模块进行克隆检测的流程图,如图6所示,主要包括以下步骤:
141.步骤一:扫描语义向量集中的向量,将开发人员上传目标代码片段的语义向量与语义向量集中的任意一个向量组成语义向量表示对。这里为了和l1对应表示,选择使用l2代表语义向量集中的任意一个语义向量,则语义向量表示对可以用(l1,l2)表示。
142.步骤二:比较聚合:输入比较聚合模型处理所述语义向量表示对(l1,l2),得到处理后的向量对(l
′1,l2)。
143.步骤三:计算相似度:根据处理过后的向量对的向量距离,计算相似度。
144.步骤四:相似度排序:将向量对的相似度排序,确定代码托管平台上具有最大相似度的代码片段。通过定义合适的阈值,判断待测目标代码片段和托管平台最大相似度代码片段是否存在克隆关系,输出检测结果。
145.克隆检测模块的核心是步骤二中使用的基于文本序列匹配的比较聚合模型,图7是比较聚合模型的框架图,如图7所示,包括对齐层、比较层和聚合层。应用到克隆检测任务中,比较聚合模型首先对两组ast路径组对应的语义向量中的单个ast路径对应的词向量进行相似度匹配,加权得到新的向量表示,然后将新向量和旧向量进行比较拼接,最后通过聚合提取特征,生成处理后的向量进行最终的相似度计算。
146.克隆检测模型关注代码片段的ast路径,通过对ast路径进行细粒度的比较聚合,克服了孪生模型粗粒度检测的局限性,将原本可能判断为不相似的两个代码之间的ast路径进行比较,从而提高了检测精确度,减少漏报误报现象。
147.用l1=(l
11
,l
12
,...,l
1n
)来表示待测目标代码片段f1的ast路径组对应的语义向量,用l2=(l
21
,l
22
,...,l
2m
)表示代码托管平台代码片段f2的ast路径组对应的语义向量,其中l
1i
或l
2j
是一组ast路径的单个ast路径对应的词向量。核心模型由对齐、比较、聚合三层组成。其中,i、j、n、m均为正整数。
148.对齐层:对齐单个ast词向量,进行细粒度比较
149.对齐层的核心任务是将目标代码片段的语义向量l1中的单个ast词向量l
1i
和语义向量集中的任一语义向量l2中单个ast词向量l
2j
对齐匹配,从而得到语义向量l1中的带注意力权重的ast词向量l
′
1i
。以上述示例性代码举例,不同代码片段f1和f2之间可能会使用相同的函数add,那么其对应的ast会出现相同的树结构,两组ast路径中某些单个ast路径相同,即l1中的l
1i
和l2中的l
2j
有可能相同。
150.因此,第一步是首先要计算词向量l
1i
和词向量l
2j
之间的相似度,可以通过点积模型、余弦相似度等计算,得到注意力矩阵e
ij
。公式(1)是使用点积模型的示例。
[0151][0152]
其中,t表示转置。
[0153]
第二步是将注意力矩阵归一化得到注意力概率分布,可以用softmax函数对注意力矩阵进行归一化得到注意力概率系数α
ij
,下面的公式(2)是归一化处理示例。
[0154][0155]
第三步是根据权重概率系数α
ij
对向量l
1i
进行加权求和,得到最后的带注意力权重的词向量l
′
1i
。下面的公式(3)为向量更新公式。
[0156]
[0157]
其中l
′
1i
是l
2j
的加权求和,直观上,中与l
1i
相关的内容将被选中,用l
′
1i
表示。
[0158]
通过对齐层,完成了目标代码片段的语义向量l1和语义向量集中的向量l2的ast路径匹配,通过注意力加权,得到对应的l
′
1i
。宏观上看,模型可以将目标代码片段f1的ast路径组更新,得到和代码托管平台代码片段f2更相似更匹配的ast路径。
[0159]
比较层:比较ast路径
[0160]
比较层的目标是将每个l
1i
(表示一组ast路径向量中的第i个ast词向量)和l
′
1i
(语义向量l1中的带注意力权重的第i个ast词向量)进行匹配,以学习两者的关联关系,得到新的向量l
1,i
。设g表示将l
1i
和l
′
1i
匹配为l
1,i
以表示比较结果的比较函数,它将l
1i
和l
′
1i
转换为一个向量来表示比较结果。
[0161]
比较的方式有很多,比如采用神经网络cnn、rnn,神经张量网络ntn,对应位置差运算再平方等等,这里选择前馈神经网络来举例说明,则用g表示由一个全连接网络和一个非线性激活函数relu组成的前馈神经网络。
[0162][0163]
其中[*
⊙
*]表示向量拼接操作。
[0164]
聚合层:输出聚合降维后的向量
[0165]
聚合层的目标是聚合比较层中的向量,做最后的特征提取,输入为比较层得到的一组比较向量输出为聚合后的向量,用l
′1表示开发人员上传目标代码片段的语义向量经过比较聚合模型处理后的向量。
[0166]
假设有两个代码片段的向量表示l1和l2经过比较聚合模型,得到对应的向量表示l
′1,然后计算向量l
′1和l2之间的相似度s:首先通过两个代码片段的向量距离d,这里可以通过欧式距离、曼哈顿距离等计算。由于代码克隆检测问题是一个二分类问题,即给定两个代码片段,需要输出0或1,0表示它们之间不相似,1表示相似。因此需要将向量距离d映射到0~1之间,这里可以通过sigmoid函数、tanh函数等做映射,其函数值表示两个代码片段的相似度。下面的公式(5)是以sigmoid函数为例的距离映射公式。
[0167]
s=sigmoid(d)∈[0,1]
ꢀꢀ
(5)
[0168]
最后,克隆检测模块将代码对的相似度从大到小排序,确定代码托管平台上具有最大相似度的代码片段,通过定义合适的阈值,判断开发人员上传代码片段和托管平台最大相似度代码片段是否存在克隆关系,输出检测结果。
[0169]
综上,本发明提供的代码克隆检测方法及系统,通过预先生成一个语义向量集,基于代码托管平台搜集代码库,对其中的源代码生成抽象语法树,遍历抽象语法树生成一组ast路径,通过词嵌入模型完成向量表示,最后保留得到语义向量集,后续在对代码进行克隆检测的过程中可以直接使用预先生成的语义向量集进行比较聚合的克隆检测,提高向量检测速度,节省时间开销,提高执行效率。本发明将抽象语法树分解为一组ast路径,通过词嵌入模型将一组ast路径组生成一个语义向量,以此作为抽象语法树的表示。这种细粒度的处理使得模型可以很好处理很深的抽象语法树,解决梯度消失问题;另一方面,在后续克隆检测中,这种将抽象语法树分解为ast路径的处理可以减少漏报误报现象,提高检测准确
率。本发明基于深度学习,采用比较聚合模型,首先对细粒度的ast路径进行相似度匹配,匹配结果加权到一个新的向量中,最后通过聚合将细粒度特征反映到整个代码片段,进行最终的相似性检测,其性能优于孪生网络模型。
[0170]
以上的具体实施例仅描述了本发明的设计原理,该描述中的部件形状,名称可以不同,不受限制。所以,本发明领域的技术人员可以对前述实施例记载的技术方案进行修改或等同替换;而这些修改和替换未脱离本发明创造宗旨和技术方案,均应属于本发明的保护范围。