CodeQL 文档

QL 简介

通过一些简单的练习和示例来学习 QL 和 CodeQL 的基础知识。

基本语法

QL 的基本语法对于任何使用过 SQL 的人来说都很熟悉,但它在某种程度上有所不同。

QL 是一种逻辑编程语言,因此它由逻辑公式构成。QL 使用常见的逻辑连接词(例如 andornot)、量词(例如 forallexists)以及其他重要的逻辑概念,例如谓词。

QL 还支持递归和聚合。这使你可以使用简单的 QL 语法编写复杂的递归查询,并直接使用聚合,例如 countsumaverage

注意

你可以在 GitHub Codespaces 中使用 CodeQL 模板(测试版)来尝试这些教程中的 QL 概念和与编程语言无关的示例。该模板包含一个指导性的 QL 使用入门,让你轻松上手。

当你准备好对实际代码库运行 CodeQL 查询时,你需要在 Visual Studio Code 中安装 CodeQL 扩展。有关说明,请参阅 GitHub 文档中的 安装适用于 Visual Studio Code 的 CodeQL

运行查询

你可以使用 适用于 VS Code 的 CodeQL 或 GitHub Codespaces 上的 CodeQL 模板 来尝试以下示例和练习。

这是一个基本查询的示例

select "hello world"

此查询返回字符串 "hello world"

更复杂的查询通常类似于以下内容

from /* ... variable declarations ... */
where /* ... logical formulas ... */
select /* ... expressions ... */

例如,此查询的结果为数字 42

from int x, int y
where x = 6 and y = 7
select x * y

请注意,int 指定 xy 的 **类型** 为“整数”。这意味着 xy 仅限于整数值。其他一些常见的类型包括:boolean (truefalse)、datefloatstring

简单练习

你可以使用一些可用于 intdatefloatbooleanstring 类型的基本函数来编写简单的查询。若要应用函数,请将其附加到参数。例如,1.toString() 将值 1 转换为字符串。请注意,在你开始键入函数时,会显示一个弹出窗口,方便你选择所需的函数。还要注意,你可以连续应用多个函数。例如,100.log().sqrt() 首先取 100 的自然对数,然后计算结果的平方根。

练习 1 - 字符串

编写一个查询,返回字符串 "lgtm" 的长度。(提示:这里 列出了可用于字符串的函数。)

查看你的答案

练习 2 - 数字

编写一个查询,返回 3^5 (35 次方) 和 245.6 的最小值的正弦值。

查看你的答案

练习 3 - 布尔值

编写一个查询,返回布尔值 false 的反面。

查看你的答案

练习 4 - 日期

编写一个查询,计算 2017 年 6 月 10 日和 9 月 28 日之间的天数。

查看你的答案

具有多个结果的示例查询

以上练习都显示了只有一个结果的查询,但实际上,许多查询具有多个结果。例如,以下查询计算 1 到 10 之间的所有 毕达哥拉斯三元组

from int x, int y, int z
where x in [1..10] and y in [1..10] and z in [1..10] and
      x*x + y*y = z*z
select x, y, z

为了简化查询,我们可以引入一个类 SmallInt,它表示 1 到 10 之间的整数。我们还可以定义一个谓词 square(),该谓词作用于该类中的整数。通过这种方式定义类和谓词,可以轻松地重复使用代码,而无需每次都重复代码。

class SmallInt extends int {
  SmallInt() { this in [1..10] }
  int square() { result = this*this }
}

from SmallInt x, SmallInt y, SmallInt z
where x.square() + y.square() = z.square()
select x, y, z

示例 CodeQL 查询

之前的示例使用了 QL 中的内置基本类型。虽然我们选择了一个查询项目,但我们没有使用该项目的数据库中的信息。以下示例查询 *确实* 使用了这些数据库,让你了解如何使用 CodeQL 来分析项目。

使用 CodeQL 库的查询可以找出代码库中的错误,并发现重要安全漏洞的变体。访问 GitHub 安全实验室 阅读有关我们最近在开源项目中发现的漏洞示例。

在运行以下示例之前,你需要安装适用于 Visual Studio Code 的 CodeQL 扩展。有关更多信息,请参阅 GitHub 文档中的 安装适用于 Visual Studio Code 的 CodeQL。你还需要导入并选择相应的编程语言的数据库。

若要导入特定编程语言的 CodeQL 库,请在查询开头键入 import <language>

import python

from Function f
where count(f.getAnArg()) > 7
select f

from 子句定义了一个变量 f,它表示一个 Python 函数。该 where 部分将函数 f 限制为那些具有超过 7 个参数的函数。最后,该 select 子句列出这些函数。

import javascript

from Comment c
where c.getText().regexpMatch("(?si).*\\bTODO\\b.*")
select c

from 子句定义了一个变量 c,它表示一个 JavaScript 注释。该 where 部分将注释 c 限制为那些包含单词 "TODO" 的注释。该 select 子句列出这些注释。

import java

from Parameter p
where not exists(p.getAnAccess())
select p

from 子句定义了一个变量 p,它表示一个 Java 参数。该 where 部分通过将参数 p 限制为那些未访问的参数来查找未使用的参数。最后,该 select 子句列出这些参数。

进一步阅读

  • 有关底层语言的更技术性描述,请参阅“QL 语言参考”。

答案

练习 1

from string s
where s = "lgtm"
select s.length()

通常有多种方法来定义查询。例如,我们还可以以更简短的形式编写上述查询

select "lgtm".length()

练习 2

from float x, float y
where x = 3.pow(5) and y = 245.6
select x.minimum(y).sin()

练习 3

from boolean b
where b = false
select b.booleanNot()

练习 4

from date start, date end
where start = "10/06/2017".toDate() and end = "28/09/2017".toDate()
select start.daysTo(end)
  • ©GitHub, Inc.
  • 条款
  • 隐私