@@ -401,6 +401,9 @@ class MallocChecker : public Checker<check::DeadSymbols,
401
401
void ReportUseZeroAllocated (CheckerContext &C, SourceRange Range,
402
402
SymbolRef Sym) const ;
403
403
404
+ void ReportFunctionPointerFree (CheckerContext &C, SVal ArgVal,
405
+ SourceRange Range, const Expr *FreeExpr) const ;
406
+
404
407
// / Find the location of the allocation for Sym on the path leading to the
405
408
// / exploded node N.
406
409
LeakInfo getAllocationSite (const ExplodedNode *N, SymbolRef Sym,
@@ -1564,6 +1567,11 @@ ProgramStateRef MallocChecker::FreeMemAux(CheckerContext &C,
1564
1567
}
1565
1568
}
1566
1569
1570
+ if (SymBase->getType ()->isFunctionPointerType ()) {
1571
+ ReportFunctionPointerFree (C, ArgVal, ArgExpr->getSourceRange (), ParentExpr);
1572
+ return nullptr ;
1573
+ }
1574
+
1567
1575
ReleasedAllocated = (RsBase != nullptr ) && (RsBase->isAllocated () ||
1568
1576
RsBase->isAllocatedOfSizeZero ());
1569
1577
@@ -2024,10 +2032,45 @@ void MallocChecker::ReportUseZeroAllocated(CheckerContext &C,
2024
2032
}
2025
2033
}
2026
2034
2035
+ void MallocChecker::ReportFunctionPointerFree (CheckerContext &C, SVal ArgVal,
2036
+ SourceRange Range,
2037
+ const Expr *FreeExpr) const {
2038
+ if (!ChecksEnabled[CK_MallocChecker])
2039
+ return ;
2040
+
2041
+ Optional<MallocChecker::CheckKind> CheckKind = getCheckIfTracked (C, FreeExpr);
2042
+ if (!CheckKind.hasValue ())
2043
+ return ;
2044
+
2045
+ if (ExplodedNode *N = C.generateErrorNode ()) {
2046
+ if (!BT_BadFree[*CheckKind])
2047
+ BT_BadFree[*CheckKind].reset (
2048
+ new BugType (CheckNames[*CheckKind], " Bad free" , " Memory Error" ));
2049
+
2050
+ SmallString<100 > Buf;
2051
+ llvm::raw_svector_ostream Os (Buf);
2052
+
2053
+ const MemRegion *MR = ArgVal.getAsRegion ();
2054
+ while (const ElementRegion *ER = dyn_cast_or_null<ElementRegion>(MR))
2055
+ MR = ER->getSuperRegion ();
2056
+
2057
+ Os << " Argument to " ;
2058
+ if (!printAllocDeallocName (Os, C, FreeExpr))
2059
+ Os << " deallocator" ;
2060
+
2061
+ Os << " is a function pointer" ;
2062
+
2063
+ auto R = llvm::make_unique<BugReport>(*BT_BadFree[*CheckKind], Os.str (), N);
2064
+ R->markInteresting (MR);
2065
+ R->addRange (Range);
2066
+ C.emitReport (std::move (R));
2067
+ }
2068
+ }
2069
+
2027
2070
ProgramStateRef MallocChecker::ReallocMemAux (CheckerContext &C,
2028
2071
const CallExpr *CE,
2029
2072
bool FreesOnFail,
2030
- ProgramStateRef State,
2073
+ ProgramStateRef State,
2031
2074
bool SuffixWithN) const {
2032
2075
if (!State)
2033
2076
return nullptr ;
0 commit comments