Author: danielmarjamaki Date: Tue May 2 06:46:12 2017 New Revision: 301913
URL: http://llvm.org/viewvc/llvm-project?rev=301913&view=rev Log: [analyzer] Detect bad free of function pointers Differential Revision: https://reviews.llvm.org/D31650 Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp cfe/trunk/test/Analysis/malloc.c Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp?rev=301913&r1=301912&r2=301913&view=diff ============================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp Tue May 2 06:46:12 2017 @@ -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::FreeMemAu } } + 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::ReportUseZeroAllocat } } +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; Modified: cfe/trunk/test/Analysis/malloc.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/malloc.c?rev=301913&r1=301912&r2=301913&view=diff ============================================================================== --- cfe/trunk/test/Analysis/malloc.c (original) +++ cfe/trunk/test/Analysis/malloc.c Tue May 2 06:46:12 2017 @@ -1774,6 +1774,16 @@ int testNoCheckerDataPropogationFromLogi 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. _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits