笔者在阅读了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
。
关于列值有如下说明:
namespace:包名
type:类名
subtypes&#x