[PATCH] D31650: [Analyzer] Detect when function pointer is freed
Anders Rönnholm via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Thu Apr 20 04:16:19 PDT 2017
AndersRonnholm updated this revision to Diff 95929.
AndersRonnholm added a comment.
Updated after comments
Repository:
rL LLVM
https://reviews.llvm.org/D31650
Files:
lib/StaticAnalyzer/Checkers/MallocChecker.cpp
test/Analysis/malloc.c
Index: test/Analysis/malloc.c
===================================================================
--- test/Analysis/malloc.c
+++ test/Analysis/malloc.c
@@ -1774,6 +1774,16 @@
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.
Index: lib/StaticAnalyzer/Checkers/MallocChecker.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/MallocChecker.cpp
+++ lib/StaticAnalyzer/Checkers/MallocChecker.cpp
@@ -392,6 +392,9 @@
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,
@@ -1516,6 +1519,11 @@
}
}
+ if (SymBase->getType()->isFunctionPointerType()) {
+ ReportFunctionPointerFree(C, ArgVal, ArgExpr->getSourceRange(), ParentExpr);
+ return nullptr;
+ }
+
ReleasedAllocated = (RsBase != nullptr) && (RsBase->isAllocated() ||
RsBase->isAllocatedOfSizeZero());
@@ -1976,6 +1984,42 @@
}
}
+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::ReallocMem(CheckerContext &C,
const CallExpr *CE,
bool FreesOnFail,
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D31650.95929.patch
Type: text/x-patch
Size: 3019 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20170420/22b37cfb/attachment-0001.bin>
More information about the cfe-commits
mailing list