CodeQL 文档

JavaScript 和 TypeScript 代码的基本查询

学习使用带有 CodeQL 扩展的 Visual Studio Code 编写和运行简单的 CodeQL 查询。

有关安装用于 Visual Studio 代码的 CodeQL 扩展的信息,请参阅“安装用于 Visual Studio Code 的 CodeQL”。

关于查询

在 JavaScript 和 TypeScript 中,任何表达式都可以转换为表达式语句。虽然这在某些情况下很方便,但它也可能很危险。例如,假设一位程序员想通过赋值 x = 42 将新值分配给变量 x。但是,他们不小心输入了两个等号,生成了比较语句 x == 42。这是有效的 JavaScript,因此不会生成任何错误。该语句只是将 x42 进行比较,然后丢弃比较结果。

您将运行的查询将查找此问题。该查询搜索那些纯粹的表达式 e,即它们的计算不会导致任何副作用,但会作为表达式语句出现。

查找用于实验的 CodeQL 数据库

在开始为 JavaScript/TypeScript 代码编写查询之前,您需要一个 CodeQL 数据库来运行它们。最简单的方法是直接从 GitHub.com 下载使用 JavaScript/TypeScript 的存储库的数据库。

  1. 在 Visual Studio Code 中,单击左侧边栏中的 **QL** 图标 CodeQL 扩展的图标。 以显示 CodeQL 扩展。
  2. 单击 **从 GitHub 获取** 或 GitHub 徽标 CodeQL 扩展选项的图标,用于从 GitHub 下载 CodeQL 数据库。,它位于 CodeQL 扩展的顶部,以打开一个条目字段。
  3. 将存储库的 URL 复制到该字段中,然后按键盘 **Enter** 键。例如,https://github.com/ajaxorg/ace
  4. 可选地,如果存储库有多个 CodeQL 数据库可用,请选择 javascript 以下载从 JavaScript/TypeScript 代码创建的数据库。

有关数据库下载进度的信息将显示在 Visual Studio Code 的右下角。下载完成后,将在 CodeQL 扩展的 **数据库** 部分中显示带有复选标记的数据库(请参阅下面的屏幕截图)。

运行快速查询

用于 Visual Studio Code 的 CodeQL 扩展将多个 **CodeQL:** 命令添加到命令面板中,包括 **快速查询**,您可以使用它在没有任何设置的情况下运行查询。

  1. 从 Visual Studio Code 中的命令面板中,选择 **CodeQL: 快速查询**。

  2. 片刻之后,将打开一个新的标签 *quick-query.ql*,您可以为当前选定的 CodeQL 数据库(此处为 javascript 数据库)编写查询。如果您被提示将工作区重新加载为多文件夹工作区以允许快速查询,请接受或使用入门工作流创建新的工作区。

    image-quick-query

  1. 在快速查询标签中,删除 select "",并将以下查询粘贴到导入语句 import javascript 下面。

    from Expr e
    where e.isPure() and
      e.getParent() instanceof ExprStmt
    select e, "This expression has no effect."
    
  1. 将查询保存在其默认位置(工作区下名为 GitHub.vscode-codeql/quick-queries 的临时“快速查询”目录中)。

  2. 右键单击查询标签,然后选择 **CodeQL: 在所选数据库上运行查询**。(或者,从命令面板中运行该命令。)

    查询将需要几分钟才能返回结果。查询完成后,结果将显示在 CodeQL 查询结果视图中,位于主编辑器视图旁边。

    查询结果列在两列中,对应于查询的 select 子句中的表达式。第一列对应于表达式 e,并链接到项目源代码中 e 出现的位置。第二列是警报消息。

../../_images/basic-js-query-results-1.png

如果找到任何匹配的代码,请单击 e 列中的一条链接以打开文件并突出显示匹配的表达式。

../../_images/basic-js-query-results-2.png

注意

如果您想将实验性查询移到更持久的位置,则需要移动整个 Quick Queries 目录。该目录是一个 CodeQL 包,具有 qlpack.yml 文件,该文件将内容定义为 JavaScript/TypeScript CodeQL 数据库的查询。有关 CodeQL 包的更多信息,请参阅“管理 CodeQL 查询包和库包”。

关于查询结构

在最初的 import 语句之后,这个简单的查询包含三个部分,它们与 SQL 查询的 FROM、WHERE 和 SELECT 部分具有类似的用途。

查询部分 目的 细节
import javascript 导入 JavaScript 和 TypeScript 的标准 CodeQL 库。 每个查询都以一个或多个 import 语句开头。
from Expr e 定义查询的变量。声明的格式为:<type> <variable name> e 被声明为一个变量,它遍历表达式。
where e.isPure() and e.getParent() instanceof ExprStmt 定义变量的条件。

e.isPure():表达式是无副作用的。

e.getParent() instanceof ExprStmt:表达式的父级是表达式语句。

select e, "This expression has no effect."

定义对每个匹配项进行报告的内容。

用于查找不良编码实践实例的查询的 select 语句始终采用以下形式:select <program element>, "<alert message>"

报告包含解释问题的字符串的表达式。

扩展查询

查询编写本质上是一个迭代过程。您编写一个简单的查询,然后在运行它时,您会发现以前没有考虑过的示例,或者发现改进的机会。

删除误报结果

浏览基本查询的结果表明可以改进它。在结果中,您可能会发现 use strict 指令。这些指令由支持严格模式的现代浏览器以特殊方式解释,因此这些表达式确实有作用。

要从结果中删除指令

  1. where 子句扩展为包含以下额外条件

    and not e.getParent() instanceof Directive
    

    现在,where 子句为

    where e.isPure() and
      e.getParent() instanceof ExprStmt and
      not e.getParent() instanceof Directive
    
  2. 重新运行查询。

    现在,结果更少了,因为 use strict 指令不再被报告。

改进后的查询在示例项目上找到了多个结果,包括以下结果

../../_images/basic-js-query-results-1.png
point.bias == -1;

按编写方式,此语句将 point.bias-1 进行比较,然后丢弃结果。最有可能的是,它原本应该是一个赋值语句 point.bias = -1

  • ©GitHub, Inc.
  • 条款
  • 隐私