https://codeql.github.com/docs/codeql-language-guides/codeql-library-for-java/
https://codeql.github.com/codeql-standard-libraries/java/

一、五大类库

Program Elements,程序元素,例如类和方法
AST nodes 抽象树节点,例如语句和表达式
Metadata 元数据,例如注解和注释
metrics,计算指标,例如循环复杂度
Call Gragh,调用图

二、程序元素

顶级类 Element

程序元素包含:packages (Package), compilation units (CompilationUnit), types (Type), methods (Method), constructors (Constructor), and variables (Variable).
点击查看【processon】

1、类型,TODO

顶级类 Type

PrimitiveType 主数据类型

boolean, byte, char, double, float, int, long, short, void, , null

RefType 引用类型

Class、Interface、EnumType、Array

查询示例:查询所有int类型的变量

  1. import java
  2. from Variable v, PrimitiveType pt
  3. where pt = v.getType() and
  4. pt.hasName("int")
  5. select v

TopLevelType
NestedType

TopLevelClass
NestedClass

2、泛型,TODO

顶级类 Type
GenericType
GenericInterface
GenericClass
TypeVariable

代码示例:查找所有java.util.Map的参数实例

  1. import java
  2. from GenericInterface map, ParameterizedType pt
  3. where map.hasQualifiedName("java.util", "Map") and
  4. pt.getSourceDeclaration() = map
  5. select pt

3、变量

顶级类 Variable

Field,Java字段
LocalVariableDecl,局部变量
Parameter,方法参数、构造器参数

三、抽象语法树

两个顶级类
Stmt,Statements语句
Expr,Expressions表达式
遍历AST
Expr.getAChildExpr
returns a sub-expression of a given expression.
Stmt.getAChild
returns a statement or expression that is nested directly inside a given statement.
Expr.getParent
Stmt.getParent
return the parent node of an AST node.

AST内容详细内容可见第10章节:Java抽象语法树

查询示例1:查询return语句内嵌套的表达式
当样本是return 1+1时,将会匹配 1+1

  1. import java
  2. from Expr e
  3. where e.getParent() instanceof ReturnStmt
  4. select e

查询示例2:查询if语句内内嵌套的表达式

  1. import java
  2. from Stmt s
  3. where s.getParent() instanceof IfStmt
  4. select s

匹配结果示例,样本来源WebGoat
image.png
image.png
查询示例3:查询方法内的语句

  1. import java
  2. from Stmt s
  3. where s.getParent() instanceof Method
  4. select s

匹配结果示例,样本来源WebGoat
image.png

四、元数据

注解顶级类:Annotatable
包括包、引用类型、字段、方法、构造器和局部变量声明,可以通过程序元素的谓词getAnAnnotation来获取。

代码示例:查询类构造器的注解

  1. import java
  2. from Constructor c
  3. select c.getAnAnnotation()

匹配结果示例,c.getAnAnnotation()的值是Inject
image.png
代码示例:查询已经废弃的构造方法

  1. import java
  2. from Constructor c, Annotation ann, AnnotationType anntp
  3. where ann = c.getAnAnnotation() and
  4. anntp = ann.getType() and
  5. anntp.hasQualifiedName("java.lang", "Deprecated")
  6. select ann

文档顶级类,Javadoc
程序元素可以使用谓词getDoc来获取Document对象

代码示例:获取私有字段的Java文档注释

  1. import java
  2. from Field f, Javadoc jdoc
  3. where f.isPrivate() and
  4. jdoc = f.getDoc().getJavadoc()
  5. select jdoc

匹配结果示例
image.png
代码示例:查询私有变量文档注释内部任意深度的作者标签

  1. import java
  2. from Field f, Javadoc jdoc, AuthorTag at
  3. where f.isPrivate() and
  4. jdoc = f.getDoc().getJavadoc() and
  5. at.getParent+() = jdoc
  6. select at

注意:如上示例中,+操作符表示at标签任意深度的父节点

五、指标,TODO

MetricElement,MetricPackage,MetricRefType,MetricField,MetricCallable,和MetricStmt
程序元素可以使用谓词getMetrics来获取指标对象

代码示例:查询循环复杂度大于40的方法

  1. import java
  2. from Method m, MetricCallable mc
  3. where mc = m.getMetrics() and
  4. mc.getCyclomaticComplexity() > 40
  5. select m

六、调用关系

顶级类Callable
可以使用Call.getCallee查询表达式所引用的方法或者构造器。(Call继承自Expr)

代码示例:查询所有名为println的调用方法

  1. import java
  2. from Call c, Method m
  3. where c.getCallee() = m and
  4. m.hasName("println")
  5. select c

匹配结果示例
image.png
代码示例:查询未被引用过的调用

  1. import java
  2. from Callable c
  3. where not exists(c.getAReference())
  4. select c