CodeQL学习笔记(4)-CodeQL for Java(程序元素)
字数 1576 2025-08-20 18:17:53

CodeQL for Java 程序元素详解

1. CodeQL基础概念

CodeQL将源代码解析为抽象语法树(AST),其中每个节点代表一个代码元素。这些元素按照源代码的嵌套结构形成分层树形结构:

  • 顶层节点通常是整个代码文件(CompilationUnit)
  • 逐层向下展开:package → class → method → variable等
  • 每个子节点代表特定的代码元素类型(package、class、method等)

CodeQL提供了一套类库来表示这些节点类型,对应Java中的各种元素类型。

2. 基本查询结构

一个典型的CodeQL查询包含以下部分:

import java  // 导入标准库

from MethodAccess ma  // 定义变量
where 
  ma.getMethod().hasName("equals") and  // 约束条件1
  ma.getArgument(0).(StringLiteral).getValue() = ""  // 约束条件2
select ma, "This comparison to empty string is inefficient, use isEmpty() instead."  // 结果输出

查询思维是迭代过程:先用较宽泛的条件定位大范围目标,再逐步添加限制条件精确筛选。

3. 程序元素类库

3.1 核心元素类

CodeQL类 Java对应元素 说明
Element - 所有程序元素的基类
Package package Java包
CompilationUnit Java源文件 编译单元
Type 类型 Java中的类型
Method 方法 Java方法
Constructor 构造函数 Java构造函数
Variable 变量 Java变量

3.2 类型系统(Type)

Type是CodeQL中表示Java类型的核心类,其继承关系如下:

Type
├── PrimitiveType (基本类型)
│   ├── boolean, byte, char, double, float, int, long, short
│   └── 还包括QL中的void和null
└── RefType (引用类型)
    ├── Class (类)
    ├── Interface (接口)
    ├── EnumType (枚举)
    ├── Array (数组)
    ├── TopLevelType/TopLevelClass (顶层类型/类)
    └── NestedType/NestedClass (嵌套类型/类)
        ├── LocalClass (局部类)
        └── AnonymousClass (匿名类)

类型查询示例

  1. 查找所有int类型的变量:
from Variable v, PrimitiveType pt
where v.getType() = pt and pt.hasName("int")
select v
  1. 查找名称与所在文件不一致的顶层类型:
from TopLevelType tl
where tl.getName() != tl.getCompilationUnit().getName()
select tl
  1. 查找直接继承Object的嵌套类:
from NestedClass nc
where nc.getASupertype() instanceof TypeObject
select nc

4. 泛型系统

4.1 泛型类型表示

CodeQL类 Java对应 说明
GenericType 泛型类型 泛型类型基类
GenericInterface 泛型接口 Map<K,V>
GenericClass 泛型类 ArrayList<E>
TypeVariable 类型参数 K,V,E
ParameterizedType 参数化类型 Map<String,File>
RawType 原始类型 如不使用泛型的Map
WildcardTypeAccess 通配符类型 ? extends Number

4.2 泛型查询示例

  1. 查找所有java.util.Map的参数化实例:
from GenericInterface map, ParameterizedType pt
where map.hasQualifiedName("java.util", "Map") and 
      pt.getSourceDeclaration() = map
select pt
  1. 查找边界为Number的类型变量:
from TypeVariable tv, TypeBound tb
where tb = tv.getATypeBound() and 
      tb.getType().hasQualifiedName("java.lang", "Number")
select tv
  1. 查找使用原始类型Map的变量:
from Variable v, RawType rt
where rt = v.getType() and 
      rt.getSourceDeclaration().hasQualifiedName("java.util", "Map")
select v
  1. 查询通配符类型的上下界:
from WildcardTypeAccess w
where w.getUpperBound().getType().hasQualifiedName("java.lang", "Number") or
      w.getLowerBound().getType().hasQualifiedName("java.lang", "Float")
select w

5. 变量系统

CodeQL类 Java对应 说明
Variable 变量 变量基类
Field 字段 类字段
LocalVariableDecl 局部变量 方法内变量
Parameter 参数 方法/构造函数参数

6. 查询优化技巧

  1. 精确匹配String类型的equals调用
from MethodAccess ma
where ma.getMethod().hasName("equals") and
      ma.getQualifier().getType() instanceof TypeString and
      ma.getArgument(0).(StringLiteral).getValue() = ""
select ma, "Use isEmpty() instead of equals(\"\")"
  1. 使用继承关系缩小范围
from Class c
where c.getASupertype().hasQualifiedName("java.util", "AbstractList")
select c
  1. 结合多条件精确查询
from Method m
where m.hasName("toString") and
      m.getDeclaringType() instanceof EnumType and
      m.isPublic() and
      not m.isOverriding()
select m

7. 总结

CodeQL for Java的核心在于理解:

  1. Java元素与CodeQL类的对应关系
  2. 类型系统的层次结构
  3. 泛型系统的表示方法
  4. 查询的迭代思维:从宽泛到精确

掌握这些核心概念后,可以构建出各种复杂的代码分析查询,用于漏洞挖掘、代码审计等场景。

CodeQL for Java 程序元素详解 1. CodeQL基础概念 CodeQL将源代码解析为抽象语法树(AST),其中每个节点代表一个代码元素。这些元素按照源代码的嵌套结构形成分层树形结构: 顶层节点通常是整个代码文件( CompilationUnit ) 逐层向下展开:package → class → method → variable等 每个子节点代表特定的代码元素类型(package、class、method等) CodeQL提供了一套类库来表示这些节点类型,对应Java中的各种元素类型。 2. 基本查询结构 一个典型的CodeQL查询包含以下部分: 查询思维是迭代过程:先用较宽泛的条件定位大范围目标,再逐步添加限制条件精确筛选。 3. 程序元素类库 3.1 核心元素类 | CodeQL类 | Java对应元素 | 说明 | |---------|-------------|------| | Element | - | 所有程序元素的基类 | | Package | package | Java包 | | CompilationUnit | Java源文件 | 编译单元 | | Type | 类型 | Java中的类型 | | Method | 方法 | Java方法 | | Constructor | 构造函数 | Java构造函数 | | Variable | 变量 | Java变量 | 3.2 类型系统(Type) Type 是CodeQL中表示Java类型的核心类,其继承关系如下: 类型查询示例 查找所有int类型的变量: 查找名称与所在文件不一致的顶层类型: 查找直接继承Object的嵌套类: 4. 泛型系统 4.1 泛型类型表示 | CodeQL类 | Java对应 | 说明 | |---------|---------|------| | GenericType | 泛型类型 | 泛型类型基类 | | GenericInterface | 泛型接口 | 如 Map<K,V> | | GenericClass | 泛型类 | 如 ArrayList<E> | | TypeVariable | 类型参数 | 如 K , V , E 等 | | ParameterizedType | 参数化类型 | 如 Map<String,File> | | RawType | 原始类型 | 如不使用泛型的 Map | | WildcardTypeAccess | 通配符类型 | 如 ? extends Number | 4.2 泛型查询示例 查找所有 java.util.Map 的参数化实例: 查找边界为Number的类型变量: 查找使用原始类型Map的变量: 查询通配符类型的上下界: 5. 变量系统 | CodeQL类 | Java对应 | 说明 | |---------|---------|------| | Variable | 变量 | 变量基类 | | Field | 字段 | 类字段 | | LocalVariableDecl | 局部变量 | 方法内变量 | | Parameter | 参数 | 方法/构造函数参数 | 6. 查询优化技巧 精确匹配String类型的equals调用 : 使用继承关系缩小范围 : 结合多条件精确查询 : 7. 总结 CodeQL for Java的核心在于理解: Java元素与CodeQL类的对应关系 类型系统的层次结构 泛型系统的表示方法 查询的迭代思维:从宽泛到精确 掌握这些核心概念后,可以构建出各种复杂的代码分析查询,用于漏洞挖掘、代码审计等场景。