在阅读了CodeQL的官方文档,熟悉相关语法后,对CodeQL中的Java进行了一番简单的研究,本文分享这一过程的一些收获。
规则的封装
通过 class 我们可以封装一系列的谓词方法,这方便我们组织并编写一系列的规则。
递归调用
class可以通过 extends 关键字申明其继承来自另外一个或多个class,我们通过使用父类或父类的谓词方法,codeql就会帮我们自动递归使用其子类。
class使用abstract进行修饰则表示该class的构造函数谓词将不起功能作用,该方式通常用于修饰Node节点、AST节点,因为它们的构造函数谓词起到类型的判断作用(instanceof)。
同样的,我们也可以使用abstract修饰class中封装的谓词方法,这样一来该谓词方法在被使用时本身不具备谓词判断逻辑,但CodeQL会递归使用其子类的谓词。我们可根据需要选择是否使用abstract修饰词,另外子类也可被abstract修饰, 更多的注解可参考官方 docs/ql-language-reference/annotations/。
如下例子中编写了多个class并声明继承RemoteFlowSource,父类RemoteFlowSource即可在使用时表示其所有子类。
流中继step只是做方法的封装,构造函数谓词不起作用,所以不需要abstract的修饰:
ModelCsv
通过 ModelCsv ,我们可以简化代码定义sink、source、flow step,并通过 kind 来使用它,简单说一下对应的三种 ModelCsv (可以在 ExtenalFlow.qll 找到它们)。
SourceModelCsv :定义 source ,列值为 namespace(); type; subtypes; name; signature; ext; output; kind 。
SinkModelCsv :定义 sink ,列值为 namespace; type; subtypes; name; signature; ext; input; kind 。
SummaryModelCsv :定义 FlowStep ,列值为 namespace; type; subtypes; name; signature; ext; input; output; kind 。
关于列值有如下说明&#x