[analyzer] Tighten up the realloc() failure path note generation...make sure we get the right realloc()!

llvm-svn: 153370
This commit is contained in:
Jordy Rose 2012-03-24 03:15:09 +00:00
parent 43a9af7352
commit 21ff76e916
1 changed files with 31 additions and 22 deletions

View File

@ -201,16 +201,22 @@ private:
protected: protected:
enum NotificationMode { enum NotificationMode {
Normal, Normal,
Complete,
ReallocationFailed ReallocationFailed
}; };
// The allocated region symbol tracked by the main analysis. // The allocated region symbol tracked by the main analysis.
SymbolRef Sym; SymbolRef Sym;
NotificationMode Mode;
public: // The mode we are in, i.e. what kind of diagnostics will be emitted.
MallocBugVisitor(SymbolRef S) : Sym(S), Mode(Normal) {} NotificationMode Mode;
// A symbol from when the primary region should have been reallocated.
SymbolRef FailedReallocSymbol;
public:
MallocBugVisitor(SymbolRef S)
: Sym(S), Mode(Normal), FailedReallocSymbol(0) {}
virtual ~MallocBugVisitor() {} virtual ~MallocBugVisitor() {}
void Profile(llvm::FoldingSetNodeID &ID) const { void Profile(llvm::FoldingSetNodeID &ID) const {
@ -1390,30 +1396,33 @@ MallocChecker::MallocBugVisitor::VisitNode(const ExplodedNode *N,
StackHint = new StackHintGeneratorForReallocationFailed(Sym, StackHint = new StackHintGeneratorForReallocationFailed(Sym,
"Reallocation failed"); "Reallocation failed");
if (SymbolRef sym = findFailedReallocSymbol(state, statePrev)) if (SymbolRef sym = findFailedReallocSymbol(state, statePrev)) {
// Is it possible to fail two reallocs WITHOUT testing in between?
assert((!FailedReallocSymbol || FailedReallocSymbol == sym) &&
"We only support one failed realloc at a time.");
BR.markInteresting(sym); BR.markInteresting(sym);
FailedReallocSymbol = sym;
}
} }
// We are in a special mode if a reallocation failed later in the path. // We are in a special mode if a reallocation failed later in the path.
} else if (Mode == ReallocationFailed) { } else if (Mode == ReallocationFailed) {
// Generate a special diagnostic for the first realloc we find. assert(FailedReallocSymbol && "No symbol to look for.");
if (!isAllocated(RS, RSPrev, S) && !isReleased(RS, RSPrev, S))
return 0;
// Check that the name of the function is realloc. // Is this is the first appearance of the reallocated symbol?
const CallExpr *CE = dyn_cast<CallExpr>(S); if (!statePrev->get<RegionState>(FailedReallocSymbol)) {
if (!CE) // If we ever hit this assert, that means BugReporter has decided to skip
return 0; // node pairs or visit them out of order.
const FunctionDecl *funDecl = CE->getDirectCallee(); assert(state->get<RegionState>(FailedReallocSymbol) &&
if (!funDecl) "Missed the reallocation point");
return 0;
StringRef FunName = funDecl->getName(); // We're at the reallocation point.
if (!(FunName.equals("realloc") || FunName.equals("reallocf"))) Msg = "Attempt to reallocate memory";
return 0; StackHint = new StackHintGeneratorForSymbol(Sym,
Msg = "Attempt to reallocate memory"; "Returned reallocated memory");
StackHint = new StackHintGeneratorForSymbol(Sym, FailedReallocSymbol = NULL;
"Returned reallocated memory"); Mode = Normal;
Mode = Normal; }
} }
if (!Msg) if (!Msg)