CodeQL学习笔记(1)-QL语法(逻辑连接词、量词、聚合词、谓词和类)
字数 798 2025-08-20 18:17:59
CodeQL学习笔记(1)-QL语法详解
基本结构
CodeQL查询的基本结构由三部分组成:
from /* 变量声明 */
where /* 逻辑公式 */
select /* 表达式 */
示例:
from int a, int b
where x = 3, y = 4
select x, y
逻辑连接词、量词和聚合词
逻辑连接词
CodeQL支持标准的逻辑运算符:and, or, not,用于组合多个条件。
量词
exists是CodeQL中常用的量词,用于判断是否存在满足条件的元素:
exists(<变量声明> | <条件表达式>)
示例:
exists(Person p | p.getName() = "test") // 判断是否存在名字为"test"的人
聚合词
CodeQL提供多种聚合函数,通用语法为:
<aggregates>(<变量声明> | <逻辑表达式(限制范围)> | <表达式(返回筛选后的数据)>)
示例:
max(int i | exists(Person p | p.getAge() = i) | i) // 获取最大年龄
有序聚合语法更简洁:
select max(Person p | | p order by p.getAge()) // 获取年龄最大的人
常用聚合函数:
min()- 最小值max()- 最大值count()- 计数avg()- 平均值sum()- 求和
谓词(Predicates)
谓词类似于其他语言中的函数,可以接受参数并返回结果。
谓词定义
predicate isSouthern(Person p) {
p.getLocation() = "south"
}
使用示例:
from Person p
where isSouthern(p)
select p
带返回值的谓词
int getAge() {
result = xxx // result是特殊变量,表示返回值
}
注意:谓词名称必须以小写字母开头。
类(Classes)
CodeQL中的类表示一种逻辑属性,用于描述满足特定条件的值。
类定义
class Southerner extends Person {
Southerner() { isSouthern(this) } // 特征谓词
}
特征谓词定义了什么样的父类对象属于这个子类。
类成员谓词
类中可以定义成员谓词(类似于方法):
class Child extends Person {
Child() { this.getAge() < 10 }
override predicate isAllowedIn(string region) {
region = this.getLocation()
}
}
类继承特性
- 多重继承:一个值可以属于多个类
- 成员谓词覆盖:
- 同级子类(继承同一父类)的覆盖会共存
- 继承链中子类的覆盖会覆盖父类的实现
- 多重继承时,必须覆盖同名成员谓词以避免歧义
示例1:同级子类共存
class OneTwo extends OneTwoThree {
override string getAString() { ... }
}
class TwoThree extends OneTwoThree {
override string getAString() { ... }
}
// 查询OneTwoThree时,两个子类的实现会共存
示例2:继承链覆盖
class Two extends TwoThree {
override string getAString() { ... }
}
// Two的实现在查询TwoThree时会覆盖TwoThree的实现
示例3:多重继承
class Two extends OneTwo, TwoThree {
Two() { this = 2 }
override string getAString() { ... } // 必须覆盖
}
综合示例
import tutorial
// 谓词定义
predicate isSouthern(Person p) {
p.getLocation() = "south"
}
predicate isBald(Person p) {
not exists(string c | p.getHairColor() = c)
}
// 类定义
class Southerner extends Person {
Southerner() { isSouthern(this) }
}
class Child extends Person {
Child() { this.getAge() < 10 }
override predicate isAllowedIn(string region) {
region = this.getLocation()
}
}
// 查询:允许进入北方的南方秃头
from Southerner s
where s.isAllowedIn("north") and isBald(s)
select s, s.getAge()
关键点总结
- CodeQL查询由
from、where、select三部分组成 exists量词用于判断存在性- 聚合函数可以统计或计算集合的特征值
- 谓词类似于函数,可以定义逻辑条件或计算
- 类表示逻辑属性,通过特征谓词定义成员资格
- 类继承中,同级子类的成员谓词会共存,继承链中子类会覆盖父类
- 多重继承时需要显式覆盖同名成员谓词
理解这些基础概念是掌握CodeQL的关键,特别是类继承和成员谓词覆盖的机制,这与传统面向对象语言有显著区别。