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. 多重继承:一个值可以属于多个类
  2. 成员谓词覆盖
    • 同级子类(继承同一父类)的覆盖会共存
    • 继承链中子类的覆盖会覆盖父类的实现
    • 多重继承时,必须覆盖同名成员谓词以避免歧义

示例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()

关键点总结

  1. CodeQL查询由fromwhereselect三部分组成
  2. exists量词用于判断存在性
  3. 聚合函数可以统计或计算集合的特征值
  4. 谓词类似于函数,可以定义逻辑条件或计算
  5. 类表示逻辑属性,通过特征谓词定义成员资格
  6. 类继承中,同级子类的成员谓词会共存,继承链中子类会覆盖父类
  7. 多重继承时需要显式覆盖同名成员谓词

理解这些基础概念是掌握CodeQL的关键,特别是类继承和成员谓词覆盖的机制,这与传统面向对象语言有显著区别。

CodeQL学习笔记(1)-QL语法详解 基本结构 CodeQL查询的基本结构由三部分组成: 示例: 逻辑连接词、量词和聚合词 逻辑连接词 CodeQL支持标准的逻辑运算符: and , or , not ,用于组合多个条件。 量词 exists 是CodeQL中常用的量词,用于判断是否存在满足条件的元素: 示例: 聚合词 CodeQL提供多种聚合函数,通用语法为: 示例: 有序聚合语法更简洁: 常用聚合函数: min() - 最小值 max() - 最大值 count() - 计数 avg() - 平均值 sum() - 求和 谓词(Predicates) 谓词类似于其他语言中的函数,可以接受参数并返回结果。 谓词定义 使用示例: 带返回值的谓词 注意:谓词名称必须以小写字母开头。 类(Classes) CodeQL中的类表示一种逻辑属性,用于描述满足特定条件的值。 类定义 特征谓词定义了什么样的父类对象属于这个子类。 类成员谓词 类中可以定义成员谓词(类似于方法): 类继承特性 多重继承 :一个值可以属于多个类 成员谓词覆盖 : 同级子类(继承同一父类)的覆盖会共存 继承链中子类的覆盖会覆盖父类的实现 多重继承时,必须覆盖同名成员谓词以避免歧义 示例1:同级子类共存 示例2:继承链覆盖 示例3:多重继承 综合示例 关键点总结 CodeQL查询由 from 、 where 、 select 三部分组成 exists 量词用于判断存在性 聚合函数可以统计或计算集合的特征值 谓词类似于函数,可以定义逻辑条件或计算 类表示逻辑属性,通过特征谓词定义成员资格 类继承中,同级子类的成员谓词会共存,继承链中子类会覆盖父类 多重继承时需要显式覆盖同名成员谓词 理解这些基础概念是掌握CodeQL的关键,特别是类继承和成员谓词覆盖的机制,这与传统面向对象语言有显著区别。