r338780 - [analyzer] Detect pointers escaped after ReturnStmt execution in MallocChecker.
Reka Kovacs via cfe-commits
cfe-commits at lists.llvm.org
Thu Aug 2 16:02:08 PDT 2018
Author: rkovacs
Date: Thu Aug 2 16:02:08 2018
New Revision: 338780
URL: http://llvm.org/viewvc/llvm-project?rev=338780&view=rev
Log:
[analyzer] Detect pointers escaped after ReturnStmt execution in MallocChecker.
Objects local to a function are destroyed right after the statement returning
(part of) them is executed in the analyzer. This patch enables MallocChecker to
warn in these cases.
Differential Revision: https://reviews.llvm.org/D49361
Added:
cfe/trunk/test/Analysis/malloc-free-after-return.cpp
Modified:
cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
cfe/trunk/test/Analysis/inner-pointer.cpp
Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp?rev=338780&r1=338779&r2=338780&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp Thu Aug 2 16:02:08 2018
@@ -161,6 +161,7 @@ class MallocChecker : public Checker<che
check::PointerEscape,
check::ConstPointerEscape,
check::PreStmt<ReturnStmt>,
+ check::EndFunction,
check::PreCall,
check::PostStmt<CallExpr>,
check::PostStmt<CXXNewExpr>,
@@ -217,6 +218,7 @@ public:
void checkPostStmt(const BlockExpr *BE, CheckerContext &C) const;
void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const;
void checkPreStmt(const ReturnStmt *S, CheckerContext &C) const;
+ void checkEndFunction(const ReturnStmt *S, CheckerContext &C) const;
ProgramStateRef evalAssume(ProgramStateRef state, SVal Cond,
bool Assumption) const;
void checkLocation(SVal l, bool isLoad, const Stmt *S,
@@ -353,7 +355,7 @@ private:
static ProgramStateRef CallocMem(CheckerContext &C, const CallExpr *CE,
ProgramStateRef State);
- ///Check if the memory associated with this symbol was released.
+ /// Check if the memory associated with this symbol was released.
bool isReleased(SymbolRef Sym, CheckerContext &C) const;
bool checkUseAfterFree(SymbolRef Sym, CheckerContext &C, const Stmt *S) const;
@@ -377,13 +379,16 @@ private:
ProgramStateRef State,
SymbolRef &EscapingSymbol) const;
- // Implementation of the checkPointerEscape callabcks.
+ // Implementation of the checkPointerEscape callbacks.
ProgramStateRef checkPointerEscapeAux(ProgramStateRef State,
const InvalidatedSymbols &Escaped,
const CallEvent *Call,
PointerEscapeKind Kind,
bool(*CheckRefState)(const RefState*)) const;
+ // Implementation of the checkPreStmt and checkEndFunction callbacks.
+ void checkEscapeOnReturn(const ReturnStmt *S, CheckerContext &C) const;
+
///@{
/// Tells if a given family/call/symbol is tracked by the current checker.
/// Sets CheckKind to the kind of the checker responsible for this
@@ -2451,7 +2456,24 @@ void MallocChecker::checkPreCall(const C
}
}
-void MallocChecker::checkPreStmt(const ReturnStmt *S, CheckerContext &C) const {
+void MallocChecker::checkPreStmt(const ReturnStmt *S,
+ CheckerContext &C) const {
+ checkEscapeOnReturn(S, C);
+}
+
+// In the CFG, automatic destructors come after the return statement.
+// This callback checks for returning memory that is freed by automatic
+// destructors, as those cannot be reached in checkPreStmt().
+void MallocChecker::checkEndFunction(const ReturnStmt *S,
+ CheckerContext &C) const {
+ checkEscapeOnReturn(S, C);
+}
+
+void MallocChecker::checkEscapeOnReturn(const ReturnStmt *S,
+ CheckerContext &C) const {
+ if (!S)
+ return;
+
const Expr *E = S->getRetValue();
if (!E)
return;
Modified: cfe/trunk/test/Analysis/inner-pointer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/inner-pointer.cpp?rev=338780&r1=338779&r2=338780&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/inner-pointer.cpp (original)
+++ cfe/trunk/test/Analysis/inner-pointer.cpp Thu Aug 2 16:02:08 2018
@@ -361,3 +361,24 @@ void func_default_arg() {
consume(c); // expected-warning {{Use of memory after it is freed}}
// expected-note at -1 {{Use of memory after it is freed}}
}
+
+struct S {
+ std::string to_string() { return s; }
+private:
+ std::string s;
+};
+
+const char *escape_via_return_temp() {
+ S x;
+ return x.to_string().c_str(); // expected-note {{Dangling inner pointer obtained here}}
+ // expected-note at -1 {{Inner pointer invalidated by call to destructor}}
+ // expected-warning at -2 {{Use of memory after it is freed}}
+ // expected-note at -3 {{Use of memory after it is freed}}
+}
+
+const char *escape_via_return_local() {
+ std::string s;
+ return s.c_str(); // expected-note {{Dangling inner pointer obtained here}}
+ // expected-note at -1 {{Inner pointer invalidated by call to destructor}}
+} // expected-warning {{Use of memory after it is freed}}
+// expected-note at -1 {{Use of memory after it is freed}}
Added: cfe/trunk/test/Analysis/malloc-free-after-return.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/malloc-free-after-return.cpp?rev=338780&view=auto
==============================================================================
--- cfe/trunk/test/Analysis/malloc-free-after-return.cpp (added)
+++ cfe/trunk/test/Analysis/malloc-free-after-return.cpp Thu Aug 2 16:02:08 2018
@@ -0,0 +1,21 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=cplusplus.NewDelete -verify %s
+
+#include "Inputs/system-header-simulator-cxx.h"
+
+struct S {
+ S() : Data(new int) {}
+ ~S() { delete Data; }
+ int *getData() { return Data; }
+
+private:
+ int *Data;
+};
+
+int *freeAfterReturnTemp() {
+ return S().getData(); // expected-warning {{Use of memory after it is freed}}
+}
+
+int *freeAfterReturnLocal() {
+ S X;
+ return X.getData();
+} // expected-warning {{Use of memory after it is freed}}
More information about the cfe-commits
mailing list