[PATCH] D31650: [Analyzer] Detect when function pointer is freed
Anders Rönnholm via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Tue Apr 4 00:42:53 PDT 2017
AndersRonnholm created this revision.
The MallocChecker does not currently detect freeing of function pointers.
Example code.
void (*fnptr)(int);
void freeIndirectFunctionPtr() {
void *p = (void*)fnptr;
free(p); // expected-warning {{Argument to free() points to a function pointer}}
}
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() points to 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,10 @@
void ReportUseZeroAllocated(CheckerContext &C, SourceRange Range,
SymbolRef Sym) const;
+ void ReportFunctionPointerFree(CheckerContext &C, SVal ArgVal,
+ SourceRange Range, const Expr *DeallocExpr,
+ const Expr *ArgExpr) 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 +1520,12 @@
}
}
+ if (SymBase->getType()->isFunctionPointerType()) {
+ ReportFunctionPointerFree(C, ArgVal, ArgExpr->getSourceRange(), ParentExpr,
+ ArgExpr);
+ return nullptr;
+ }
+
ReleasedAllocated = (RsBase != nullptr) && (RsBase->isAllocated() ||
RsBase->isAllocatedOfSizeZero());
@@ -1976,6 +1986,47 @@
}
}
+void MallocChecker::ReportFunctionPointerFree(CheckerContext &C, SVal ArgVal,
+ SourceRange Range,
+ const Expr *DeallocExpr,
+ const Expr *ArgExpr) const {
+
+ if (!ChecksEnabled[CK_MallocChecker])
+ return;
+
+ Optional<MallocChecker::CheckKind> CheckKind =
+ getCheckIfTracked(C, DeallocExpr);
+ 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, DeallocExpr))
+ Os << "deallocator";
+
+ if (ArgExpr->IgnoreParenCasts()->getType()->isFunctionPointerType())
+ Os << " is a function pointer";
+ else
+ Os << " points to 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.94012.patch
Type: text/x-patch
Size: 3339 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20170404/314b26ca/attachment.bin>
More information about the cfe-commits
mailing list