C 和 C++ 中的函数¶
您可以使用 CodeQL 来探索 C 和 C++ 代码中的函数。
查找所有静态函数¶
使用成员谓词 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."
此查询返回的结果更少。但是,如果您检查结果,则可能仍然可以找到潜在的改进。
例如,有一个更复杂的标准查询,未使用的静态函数,用于查找未使用的静态函数。
您可以探索标准库中元素的定义,并查看可用的谓词。右键单击该元素以显示上下文菜单,然后单击“转到定义”。库文件将在新选项卡中打开,并突出显示该元素的定义。
查找特定函数¶
此查询使用 Function
和 FunctionCall
来查找对函数 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
。
此查询的发布版本要复杂得多,但如果仔细观察,您会发现其结构是相同的。请参阅非常量格式字符串。