博客 阅读时间 2 分钟

检测 C/C++ 项目中的混淆命名

分享本文
Detect Obfuscated Names in a C/C++ Project

您有多少次遇到过这样的代码?

obfuscatednames

在某些情况下,这样的代码可能不是大问题。但如果开发者频繁使用这种编码习惯,就可能给公司带来高昂的代价。每个需要调试代码或添加新功能的新人,都要花费大量时间去理解现有代码库。

我们该如何检测这些混淆的名称,以便对它们进行重构呢?

1. 使用 clang-query 和 AST Matchers

Clang 的 LibASTMatchers 是一个强大的库,用于匹配 AST 中的节点并执行使用匹配节点的代码。与LibTooling结合使用时,LibASTMatchers 有助于编写代码到代码的转换工具或查询工具。

clang-query工具基于 LibASTMatchers,提供了一种查询特定源文件 AST 节点的简便方式。

例如,如果我们想检测名称只包含一个字符的函数,可以执行这个 AST 匹配器:

functionDecl(matchesName("^[a-zA-Z]$"))

AST Matchers 为查询代码库提供了强大的方式。下面是AST Matchers 文档。

AST 匹配器是 AST 节点上的谓词。匹配器通过调用创建函数来构建,这些函数允许搭建一棵匹配器树,内部匹配器用于让匹配更加具体。

例如,要创建一个匹配翻译单元 AST 中所有类或联合声明的匹配器,可以调用recordDecl()。要进一步缩小匹配范围,比如找出所有名为"Foo"的类或联合声明,可以插入一个hasName匹配器:调用recordDecl(hasName("Foo"))会返回一个匹配器,它匹配任何命名空间中名为"Foo"的类或联合。默认情况下,接受多个内部匹配器的匹配器使用隐式的allOf()。这允许进一步缩小匹配范围,例如匹配所有派生自"Bar"的类:recordDecl(hasName("Foo"), isDerivedFrom("Bar"))。

2. 使用 CppDepend 和 CQLinq

CppDepend 自带 CQLinq,一种用于查询代码库的代码查询语言。

CQLinq 定义了多个可查询的预定义域,包括:Types(类型);Methods;Fields(字段);Namespaces(命名空间);Projects(项目)

这些域不仅枚举被查询代码库中的所有代码元素,还枚举代码库使用的所有第三方代码元素(例如类型string以及代码库使用的类型string的所有方法和字段)。

语法非常简单:

from m in Methods where m.NbLinesOfCode > 30 select m

要检测名称只包含一个字符的函数,我们可以执行下面的 CQLinq 查询:

Untitled2

结论:

不要低估符号名称的重要性;好的名称让代码库更易于理解和维护。将构建过程自动化以检测命名不当的符号,可以帮助提高代码库的整体质量。

分享本文