Refactoring:

+ Individual Report* method for each bug type
+ Comment improved: missing non-trivial alloca() case annotated
+ 'range' parameter of ReportBadFree() capitalized
+ 'SymbolRef Sym = State->getSVal(A, C.getLocationContext()).getAsSymbol();' shorten to 'SymbolRef Sym = C.getSVal(A).getAsSymbol();'

llvm-svn: 176949
This commit is contained in:
Anton Yartsev 2013-03-13 14:39:10 +00:00
parent 3605f319dd
commit 59ed15b052
1 changed files with 55 additions and 34 deletions

View File

@ -229,8 +229,14 @@ private:
static bool SummarizeValue(raw_ostream &os, SVal V);
static bool SummarizeRegion(raw_ostream &os, const MemRegion *MR);
void ReportBadFree(CheckerContext &C, SVal ArgVal, SourceRange range) const;
void ReportBadFree(CheckerContext &C, SVal ArgVal, SourceRange Range) const;
void ReportBadDealloc(CheckerContext &C, SourceRange Range,
const Expr *DeallocExpr, const RefState *RS) const;
void ReportOffsetFree(CheckerContext &C, SVal ArgVal, SourceRange Range)const;
void ReportUseAfterFree(CheckerContext &C, SourceRange Range,
SymbolRef Sym) const;
void ReportDoubleFree(CheckerContext &C, SourceRange Range, bool Released,
SymbolRef Sym, bool Interesting) const;
/// Find the location of the allocation for Sym on the path leading to the
/// exploded node N.
@ -714,7 +720,8 @@ ProgramStateRef MallocChecker::FreeMemAux(CheckerContext &C,
const MemSpaceRegion *MS = R->getMemorySpace();
// Parameters, locals, statics, and globals shouldn't be freed.
// Parameters, locals, statics, globals, and memory returned by alloca()
// shouldn't be freed.
if (!(isa<UnknownSpaceRegion>(MS) || isa<HeapSpaceRegion>(MS))) {
// FIXME: at the time this code was written, malloc() regions were
// represented by conjured symbols, which are all in UnknownSpaceRegion.
@ -742,22 +749,8 @@ ProgramStateRef MallocChecker::FreeMemAux(CheckerContext &C,
if (RsBase &&
(RsBase->isReleased() || RsBase->isRelinquished()) &&
!didPreviousFreeFail(State, SymBase, PreviousRetStatusSymbol)) {
if (ExplodedNode *N = C.generateSink()) {
if (!BT_DoubleFree)
BT_DoubleFree.reset(
new BugType("Double free", "Memory Error"));
BugReport *R = new BugReport(*BT_DoubleFree,
(RsBase->isReleased() ? "Attempt to free released memory"
: "Attempt to free non-owned memory"),
N);
R->addRange(ArgExpr->getSourceRange());
R->markInteresting(SymBase);
if (PreviousRetStatusSymbol)
R->markInteresting(PreviousRetStatusSymbol);
R->addVisitor(new MallocBugVisitor(SymBase));
C.emitReport(R);
}
ReportDoubleFree(C, ParentExpr->getSourceRange(), RsBase->isReleased(),
SymBase, PreviousRetStatusSymbol);
return 0;
}
@ -884,7 +877,7 @@ bool MallocChecker::SummarizeRegion(raw_ostream &os,
}
void MallocChecker::ReportBadFree(CheckerContext &C, SVal ArgVal,
SourceRange range) const {
SourceRange Range) const {
if (ExplodedNode *N = C.generateSink()) {
if (!BT_BadFree)
BT_BadFree.reset(new BugType("Bad free", "Memory Error"));
@ -917,7 +910,7 @@ void MallocChecker::ReportBadFree(CheckerContext &C, SVal ArgVal,
BugReport *R = new BugReport(*BT_BadFree, os.str(), N);
R->markInteresting(MR);
R->addRange(range);
R->addRange(Range);
C.emitReport(R);
}
}
@ -957,6 +950,43 @@ void MallocChecker::ReportOffsetFree(CheckerContext &C, SVal ArgVal,
C.emitReport(R);
}
void MallocChecker::ReportUseAfterFree(CheckerContext &C, SourceRange Range,
SymbolRef Sym) const {
if (ExplodedNode *N = C.generateSink()) {
if (!BT_UseFree)
BT_UseFree.reset(new BugType("Use-after-free", "Memory Error"));
BugReport *R = new BugReport(*BT_UseFree,
"Use of memory after it is freed", N);
R->markInteresting(Sym);
R->addRange(Range);
R->addVisitor(new MallocBugVisitor(Sym));
C.emitReport(R);
}
}
void MallocChecker::ReportDoubleFree(CheckerContext &C, SourceRange Range,
bool Released, SymbolRef Sym,
bool Interesting) const {
if (ExplodedNode *N = C.generateSink()) {
if (!BT_DoubleFree)
BT_DoubleFree.reset(new BugType("Double free", "Memory Error"));
BugReport *R = new BugReport(*BT_DoubleFree,
(Released ? "Attempt to free released memory"
: "Attempt to free non-owned memory"),
N);
R->addRange(Range);
if (Interesting)
R->markInteresting(Sym);
R->addVisitor(new MallocBugVisitor(Sym));
C.emitReport(R);
}
}
ProgramStateRef MallocChecker::ReallocMem(CheckerContext &C,
const CallExpr *CE,
bool FreesOnFail) const {
@ -1222,7 +1252,7 @@ void MallocChecker::checkPreStmt(const CallExpr *CE, CheckerContext &C) const {
E = CE->arg_end(); I != E; ++I) {
const Expr *A = *I;
if (A->getType().getTypePtr()->isAnyPointerType()) {
SymbolRef Sym = State->getSVal(A, C.getLocationContext()).getAsSymbol();
SymbolRef Sym = C.getSVal(A).getAsSymbol();
if (!Sym)
continue;
if (checkUseAfterFree(Sym, C, A))
@ -1303,21 +1333,12 @@ bool MallocChecker::isReleased(SymbolRef Sym, CheckerContext &C) const {
bool MallocChecker::checkUseAfterFree(SymbolRef Sym, CheckerContext &C,
const Stmt *S) const {
if (isReleased(Sym, C)) {
if (ExplodedNode *N = C.generateSink()) {
if (!BT_UseFree)
BT_UseFree.reset(new BugType("Use-after-free", "Memory Error"));
BugReport *R = new BugReport(*BT_UseFree,
"Use of memory after it is freed",N);
if (S)
R->addRange(S->getSourceRange());
R->markInteresting(Sym);
R->addVisitor(new MallocBugVisitor(Sym));
C.emitReport(R);
return true;
}
if (isReleased(Sym, C)) {
ReportUseAfterFree(C, S->getSourceRange(), Sym);
return true;
}
return false;
}