文章目录
现在用joern来构建代码属性图。joern可以生成AST,CFG,PDG,然后将这三者全部融合在一起。对于GNN来说,输入需要各个节点的属性以及节点之间的关系。因此,下面有两种方式来用joern构建,一种是直接用其生成的CPG来进行处理;第二种方式是分别将生成的三种结构进行组合。
用joern生成的这三种图的存储方式都可以通过json对象或者json string的形式进行存储。(那么这三种结构中的节点,是否能够统一联系在一起?)
AST
用joern可以将函数解析出来生成AST,这个AST的数据是以json的格式进行存储的。为了方便批量处理数据,我们用将json用Python转换成字典的形式。
-
解析文件并生成AST。如果直接将一个函数实体通过此命令进行解析
cpg.runScript(graph/ast-for-funcs-dumps.sc)
,那会将此函数以及其内部的函数都生成一个AST,然后这些AST都存在dict["functions"]
中,这是一个列表,其中每个元素是以字典形式存储的每个函数的AST。每个AST字典第一个键值对表明此AST是哪个函数key = function value = function_name
。我们只要主函数的AST,因此我们首先需要知道主函数的函数名,然后通过在键值对查询找到相应的字典(AST)。 -
找到所有的节点及需要的节点信息。
对于每个AST(字典),它的结构是这样的,主要有三个键,function、id、AST。function表示的是此函数的函数名。id是每个节点或者边的编号,其格式是
io.shiftleft.codepropertygraph.generated.nodes.Method@49
.nodes
表示这是AST的一个节点,.Method
表示这个节点的类型是一个方法,@49
是这个节点的标号(应该是十六进制)。这个node是此AST的首节点,其余的节点和边都是由此节点发散出来。AST表示的是此函数的具体ast结构,用列表进行存储的,其中每个元素是一个字典(这个字典用来存储AST的每个节点的信息,包括了节点的id、边的信息和其它的一些信息)key = id
这个id 键存储了节点的类型和编号,其主要类型有 Method、MethodParameterIn、MethodParameterOut、Identifier、Call…key = edges
这个edges存储了与此节点相连的所有边,其value是列表的形式,其中每个元素是一条边(用一个字典进行存储)。具体边的信息在下面详细介绍。key = properties
这个properties存储了与此节点相关的信息,其value是列表的形式。列表的每个元素是一个property(用一个字典进行存储,这个字典只有两个键值对,两个键分别是key和value。在key的value中,有这么几种类别,NAME、ORDER、CODE、EVALUATION_STRATEGY、TYPE_FULLNAME、ARGUMENT_INDEX) -
找到所有的边以及边的属性。
这个AST的边是存在AST字典的里。其存储的形式是依靠每个节点,如果节点上有相关的边,那么这些边的信息就会以一个字典的结构存储。每条边共有三个键,id、in、out。id是表示该边的类型和编号,比如AST边就是
edges.Ast@
。如果是CFG边则是edges.Cfg@
。in 是表示边的源节点的id,out表示的是边的终止节点的id。
ut表示的是边的终止节点的id。