diff options
author | Daniel Marjamaki <daniel.marjamaki@evidente.se> | 2017-05-02 11:46:12 +0000 |
---|---|---|
committer | Daniel Marjamaki <daniel.marjamaki@evidente.se> | 2017-05-02 11:46:12 +0000 |
commit | a43a8f5c5ed0757caad574ec0567a211b9e67f78 (patch) | |
tree | 958c95767664f326bf258e093e5f00073943269f | |
parent | 24d361f7bf66cc3f6c131223fec956d225f27680 (diff) | |
download | bcm5719-llvm-a43a8f5c5ed0757caad574ec0567a211b9e67f78.tar.gz bcm5719-llvm-a43a8f5c5ed0757caad574ec0567a211b9e67f78.zip |
[analyzer] Detect bad free of function pointers
Differential Revision: https://reviews.llvm.org/D31650
llvm-svn: 301913
-rw-r--r-- | clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp | 45 | ||||
-rw-r--r-- | clang/test/Analysis/malloc.c | 10 |
2 files changed, 54 insertions, 1 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp index 5730517289b..9a7e83c1492 100644 --- a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -401,6 +401,9 @@ private: void ReportUseZeroAllocated(CheckerContext &C, SourceRange Range, SymbolRef Sym) const; + void ReportFunctionPointerFree(CheckerContext &C, SVal ArgVal, + SourceRange Range, const Expr *FreeExpr) const; + /// Find the location of the allocation for Sym on the path leading to the /// exploded node N. LeakInfo getAllocationSite(const ExplodedNode *N, SymbolRef Sym, @@ -1564,6 +1567,11 @@ ProgramStateRef MallocChecker::FreeMemAux(CheckerContext &C, } } + if (SymBase->getType()->isFunctionPointerType()) { + ReportFunctionPointerFree(C, ArgVal, ArgExpr->getSourceRange(), ParentExpr); + return nullptr; + } + ReleasedAllocated = (RsBase != nullptr) && (RsBase->isAllocated() || RsBase->isAllocatedOfSizeZero()); @@ -2024,10 +2032,45 @@ void MallocChecker::ReportUseZeroAllocated(CheckerContext &C, } } +void MallocChecker::ReportFunctionPointerFree(CheckerContext &C, SVal ArgVal, + SourceRange Range, + const Expr *FreeExpr) const { + if (!ChecksEnabled[CK_MallocChecker]) + return; + + Optional<MallocChecker::CheckKind> CheckKind = getCheckIfTracked(C, FreeExpr); + if (!CheckKind.hasValue()) + return; + + if (ExplodedNode *N = C.generateErrorNode()) { + if (!BT_BadFree[*CheckKind]) + BT_BadFree[*CheckKind].reset( + new BugType(CheckNames[*CheckKind], "Bad free", "Memory Error")); + + SmallString<100> Buf; + llvm::raw_svector_ostream Os(Buf); + + const MemRegion *MR = ArgVal.getAsRegion(); + while (const ElementRegion *ER = dyn_cast_or_null<ElementRegion>(MR)) + MR = ER->getSuperRegion(); + + Os << "Argument to "; + if (!printAllocDeallocName(Os, C, FreeExpr)) + Os << "deallocator"; + + Os << " is a function pointer"; + + auto R = llvm::make_unique<BugReport>(*BT_BadFree[*CheckKind], Os.str(), N); + R->markInteresting(MR); + R->addRange(Range); + C.emitReport(std::move(R)); + } +} + ProgramStateRef MallocChecker::ReallocMemAux(CheckerContext &C, const CallExpr *CE, bool FreesOnFail, - ProgramStateRef State, + ProgramStateRef State, bool SuffixWithN) const { if (!State) return nullptr; diff --git a/clang/test/Analysis/malloc.c b/clang/test/Analysis/malloc.c index d5f2cfedd18..4c364ebd9a2 100644 --- a/clang/test/Analysis/malloc.c +++ b/clang/test/Analysis/malloc.c @@ -1774,6 +1774,16 @@ int testNoCheckerDataPropogationFromLogicalOpOperandToOpResult(void) { return ok; // no warning } +void (*fnptr)(int); +void freeIndirectFunctionPtr() { + void *p = (void *)fnptr; + free(p); // expected-warning {{Argument to free() is a function pointer}} +} + +void freeFunctionPtr() { + free((void *)fnptr); // expected-warning {{Argument to free() is a function pointer}} +} + // ---------------------------------------------------------------------------- // False negatives. |