clang analyzer: exit of CompoundStmt

Hi,

I’m currently trying to implement a clang analyzer check
to detect dangling pointers to a local (that went out of scope), like in:

void pointer_leaves_scope(bool bb) {

int* p;
{

int i = 0;
p = &i;
} // need to get a callback here
*p = 1; // should produce warning: i went out-of-scope
}

I first though that checkDeadSymbols(…) will be called when i goes out of scope,
but it does not. Seems that I don’t understand what checkDeadSymbols is supposed to do.

I also tried checkPostStmt(CompoundStmt*,…), but that is not called either.

Now I’m looking how to implement this callback (could be named checkSymbolLeavesScope).
Or something like checkEndFunction() but for all local scopes.

Could anyone please give me some hints where to add this to the analyzer core?
I’m I missing something obvious?

Thanks,

Matthias

Matthias,

I can at least give you a partial solution. The reason that checkDeadSymbols() is not triggered by ‘i’ going out of scope is that ‘i’ is not symbolic. Symbols refer to values which the analyzer cannot properly model, other than by assigning constraints to them. Since ‘i’ is declared locally, and a reference to ‘i’ never leaves this translation unit, ‘i’ is never assigned a symbolic value. I think that what you need is provided by the analysis context. You can do something like:

const CFGBlock *currentBlock = Ctx.getLocationContext()->getCurrentStackFrame()->getCallSiteBlock();
LiveVariables *analysisLV = Ctx.getLocationContext()->getAnalysis();
if (!analysisLV->isLive(currentBlock, iVar)) {
// iVar went out of scope, handle it somehow
}

The next question would be concern which callback to hook. Although checkEndFunction() would be the easiest, it’s not precise enough to handle compoundStmts. But I’m not aware of a better option (someone else might be?).

~Scott

Matthias,

I can at least give you a partial solution. The reason that checkDeadSymbols() is not triggered by ‘i’ going out of scope is that ‘i’ is not symbolic. Symbols refer to values which the analyzer cannot properly model, other than by assigning constraints to them. Since ‘i’ is declared locally, and a reference to ‘i’ never leaves this translation unit, ‘i’ is never assigned a symbolic value. I think that what you need is provided by the analysis context. You can do something like:

const CFGBlock *currentBlock = Ctx.getLocationContext()->getCurrentStackFrame()->getCallSiteBlock();
LiveVariables *analysisLV = Ctx.getLocationContext()->getAnalysis();
if (!analysisLV->isLive(currentBlock, iVar)) {
// iVar went out of scope, handle it somehow
}

Unfortunately, I don’t think the live variables analysis will quite do what is needed because it determines whether the value stored in the variable may be later read — it doesn’t say when the underlying storage for the variable will disappear.

For example:

int p = 5;
p = 6;
// Live variables says p is dead here.
p = 7;
// Live variables says p is alive here.
printf(“p is %d\n”, p);

The next question would be concern which callback to hook. Although checkEndFunction() would be the easiest, it’s not precise enough to handle compoundStmts. But I’m not aware of a better option (someone else might be?).

We don’t have a hook to tell checkers when a variable has gone out of scope, although it probably wouldn’t be that difficult to add. With this callback, you could iterate over the bindings in the heap to determine when there is a reference to out-of-scope storage. We currently do something similar in StackAddrEscapeChecker::checkEndFunction() to issue a diagnostic when the address of a local variable is stored in a global (StackAddrEscapeChecker could probably also be extended to handle storing local addresses in the heap).

Devin