如何从clang::ento::nonloc::ConcreteInt类型SVal获取源MemRegion?
在Clang静态分析器中追踪ConcreteInt的源MemRegion方案
核心思路:在初始化阶段绑定常量与来源区域
当变量被初始化为常量时,Clang静态分析器默认会生成nonloc::ConcreteInt,不会保留它的来源信息。要解决这个问题,得在变量初始化的早期阶段就把常量和对应的源MemRegion绑定,而不是等到checkBind阶段再补救,具体可以从这几个方向入手:
1. 用checkPostStmt拦截变量声明语句
针对DeclStmt类型的语句,直接从AST里拿到变量的初始化表达式:
- 如果初始化的是另一个变量(比如
int a = b;),直接提取这个变量对应的MemRegion; - 如果是字面量(比如
int a = 5;),就把这个字面量和当前变量的MemRegion关联起来,存在ProgramState里,后续在checkBind里就能通过这个关联找到来源。
代码示例:
void checkPostStmt(const DeclStmt *DS, CheckerContext &C) const { for (const auto *D : DS->decls()) { if (const auto *VD = dyn_cast<VarDecl>(D)) { if (VD->hasInit()) { const Expr *InitE = VD->getInit(); SVal InitVal = C.getSVal(InitE); MemRegion *VarRegion = C.getSVal(VD).getAsRegion(); if (const auto *CI = InitVal.getAs<nonloc::ConcreteInt>()) { // 用自定义的State扩展存储关联关系 ProgramStateRef NewState = C.getState()->set<ConcreteIntRegionMap>(CI->getValue(), VarRegion); C.addTransition(NewState); } } } } }
2. 自定义符号包裹ConcreteInt,携带来源信息
如果要更严谨的路径敏感追踪,可以自己写一个SymExpr的子类,把ConcreteInt和对应的MemRegion打包在一起。在初始化变量的时候,不用默认的ConcreteInt,而是用这个自定义符号,后续分析时只要识别出这个自定义符号,就能拿到来源区域。
步骤大概是:
- 定义
ConcreteIntWithRegionSym类,继承SymExpr,包含ConcreteInt和MemRegion*成员; - 在变量初始化回调里,把原本的
ConcreteInt替换成这个自定义符号; - 在
checkBind或者其他检查点里,判断符号类型,提取里面的MemRegion。
3. 尝试从SVal的符号依赖链溯源
有些情况下,ConcreteInt可能隐含符号依赖(比如常量来自宏或者其他变量的传递),可以试试调用SVal::getAsSymbol()或者遍历符号依赖树,看看能不能找到关联的MemRegion。不过这个方法对纯字面量初始化的场景作用不大,更适合有变量传递的情况。
注意点
- 所有修改都不能破坏原有路径敏感分析的流程,只能在现有
ProgramState上添加自定义数据; - 全局变量、静态变量的初始化要单独处理,比如在
checkBeginFunction或者checkEndTranslationUnit回调里做; - 存储关联关系的时候,一定要用Clang提供的
ProgramState扩展机制,别自己乱存导致内存泄漏或者状态不一致。
内容的提问来源于stack exchange,提问作者Gruber
相关产品推荐
相关产品推荐

