CodeQL 文档

C 和 C++ 中的函数

您可以使用 CodeQL 来探索 C 和 C++ 代码中的函数。

概述

C 和 C++ 的标准 CodeQL 库使用 Function 类表示函数(请参阅C 和 C++ 的 CodeQL 库)。

本主题中的示例查询探索了一些用于查询函数的最有用的库谓词。

查找所有静态函数

使用成员谓词 Function.isStatic(),我们可以列出数据库中的所有静态函数

import cpp

from Function f
where f.isStatic()
select f, "This is a static function."

此查询非常通用,因此对于大多数非平凡项目来说,结果可能太多而无意义。

查找未被调用的函数

使用抽象语法树类别中的标准 CodeQL FunctionCall 类(请参阅C 和 C++ 的 CodeQL 库)查找未被调用的函数可能会更有趣。FunctionCall 类可用于标识实际使用函数的位置,并通过 FunctionCall.getTarget() 谓词与 Function 相关联。

import cpp

from Function f
where not exists(FunctionCall fc | fc.getTarget() = f)
select f, "This function is never called."

新查询查找不是任何 FunctionCall 目标的函数,换句话说,就是从未被调用的函数。您可能会对查询找到的结果数量感到惊讶。但是,如果检查结果,您会发现它找到的许多函数都是间接使用的。要创建一个仅查找未使用函数的查询,我们需要优化查询并排除使用函数的其他方式。

排除使用函数指针引用的函数

您可以修改查询以删除使用函数指针引用函数的函数

import cpp

from Function f
where not exists(FunctionCall fc | fc.getTarget() = f)
  and not exists(FunctionAccess fa | fa.getTarget() = f)
select f, "This function is never called, or referenced with a function pointer."

此查询返回的结果更少。但是,如果您检查结果,则可能仍然可以找到潜在的改进。

例如,有一个更复杂的标准查询,未使用的静态函数,用于查找未使用的静态函数。

您可以探索标准库中元素的定义,并查看可用的谓词。右键单击该元素以显示上下文菜单,然后单击“转到定义”。库文件将在新选项卡中打开,并突出显示该元素的定义。

查找特定函数

此查询使用 FunctionFunctionCall 来查找对函数 sprintf 的调用,这些调用具有可变格式字符串,这可能存在安全隐患。

import cpp

from FunctionCall fc
where fc.getTarget().getQualifiedName() = "sprintf"
  and not fc.getArgument(1) instanceof StringLiteral
select fc, "sprintf called with variable format string."

这使用

  • Declaration.getQualifiedName() 来标识对特定函数 sprintf 的调用。
  • FunctionCall.getArgument(1) 来获取格式字符串参数。

请注意,我们可以使用 Declaration.getName(),但 Declaration.getQualifiedName() 是更好的选择,因为它包含命名空间。例如:getName() 将返回 vector,而 getQualifiedName 将返回 std::vector

此查询的发布版本要复杂得多,但如果仔细观察,您会发现其结构是相同的。请参阅非常量格式字符串

  • ©GitHub 公司
  • 条款
  • 隐私