CodeQL 文档

哈希合并和值编号

您可以使用专门的 CodeQL 库来识别在 C 和 C++ 代码库中语法上相同或在运行时计算相同值的表达式。

关于哈希合并和值编号库

在 C 和 C++ 数据库中,抽象语法树中的每个节点都由一个单独的对象表示。这允许分析和结果显示都引用语法片段的特定出现。但是,确定两个表达式是否等效(无论是语法上还是语义上)通常很有用。

哈希合并库(在 semmle.code.cpp.valuenumbering.HashCons 中定义)提供了一种机制来识别具有相同语法结构的表达式。全局值编号库(在 semmle.code.cpp.valuenumbering.GlobalValueNumbering 中定义)提供了一种机制来识别在运行时计算相同值的表达式。这两个库都将每个函数中的表达式划分成由对象表示的等效类。每个 HashCons 对象代表一组具有相同解析树的表达式,而 GVN 对象代表一组始终计算相同值的表达式。有关更多信息,请参阅维基百科上的 哈希合并值编号

示例 C 代码

在以下 C 程序中,x + yx + z 将被分配相同的数值,但哈希合并不同。

int x = 1;
int y = 2;
int z = y;
if(x + y == x + z) {
  ...
}

但是,在下一个示例中,x + y 的使用将具有不同的数值,但相同的哈希合并。

int x = 1;
int y = 2;
if(x + y) {
  ...
}

x = 2;

if(x + y) {
  ...
}

值编号

值编号库(在 semmle.code.cpp.valuenumbering.GlobalValueNumbering 中定义)提供了一种机制来识别在运行时计算相同值的表达式。当您主要关注的是正在产生的值或最终运行的机器码时,值编号很有用。例如,值编号可用于确定是否对与保护它的操作相同的数值进行了检查。

值编号 API

值编号库主要通过 GVN 类公开其接口。每个 GVN 实例代表一组始终计算相同值的表达式。要获取特定 GVN 代表的集合中的表达式,请使用 getAnExpr() 成员谓词。

要获取 ExprGVN,请使用 globalValueNumber 谓词。

注意

虽然 GVN 类具有 toStringgetLocation 方法,但这些方法仅作为调试辅助手段提供。它们给出了集合中任意 ExprtoStringgetLocation

为什么不是谓词?

这个库的明显接口将是一个谓词 equivalent(Expr e1, Expr e2)。但是,这个谓词将非常大,对于每组等效表达式,将具有二次数量的行。通过使用类作为中间步骤,可以将行数保持为线性,因此可以进行缓存。

示例查询

此查询使用 GVN 类来识别对 strncpy 的调用,其中大小参数是从源代码而不是目标代码派生的

from FunctionCall strncpy, FunctionCall strlen
where
  strncpy.getTarget().hasGlobalName("strncpy") and
  strlen.getTarget().hasGlobalName("strlen") and
  globalValueNumber(strncpy.getArgument(1)) = globalValueNumber(strlen.getArgument(0)) and
  strlen = strncpy.getArgument(2)
select ci, "This call to strncpy is bounded by the size of the source rather than the destination"

哈希合并

哈希合并库(在 semmle.code.cpp.valuenumbering.HashCons 中定义)提供了一种机制来识别具有相同语法结构的表达式。当您主要关注代码文本时,哈希合并很有用。例如,哈希合并可用于检测函数内的重复代码。

哈希合并 API

哈希合并库主要通过 HashCons 类公开其接口。每个 HashCons 实例代表一个函数内具有相同语法的表达式集(包括引用相同的变量)。要获取特定 HashCons 代表的集合中的表达式,请使用 getAnExpr() 成员谓词。

注意

虽然 HashCons 类具有 toStringgetLocation 方法,但这些方法仅作为调试辅助手段提供。它们给出了集合中任意 ExprtoStringgetLocation

要获取 ExprHashCons,请使用 hashCons 谓词。

示例查询

import cpp
import semmle.code.cpp.valuenumbering.HashCons

from IfStmt outer, IfStmt inner
where
  outer.getElse+() = inner and
  hashCons(outer.getCondition()) = hashCons(inner.getCondition())
select inner.getCondition(), "The condition of this if statement duplicates the condition of $@",
  outer.getCondition(), "an enclosing if statement"
  • ©GitHub, Inc.
  • 条款
  • 隐私