r174677 - [analyzer] Add pointer escape type param to checkPointerEscape callback
Anna Zaks
ganna at apple.com
Thu Feb 7 15:05:44 PST 2013
Author: zaks
Date: Thu Feb 7 17:05:43 2013
New Revision: 174677
URL: http://llvm.org/viewvc/llvm-project?rev=174677&view=rev
Log:
[analyzer] Add pointer escape type param to checkPointerEscape callback
The checkPointerEscape callback previously did not specify how a
pointer escaped. This change includes an enum which describes the
different ways a pointer may escape. This enum is passed to the
checkPointerEscape callback when a pointer escapes. If the escape
is due to a function call, the call is passed. This changes
previous behavior where the call is passed as NULL if the escape
was due to indirectly invalidating the region the pointer referenced.
A patch by Branden Archer!
Modified:
cfe/trunk/include/clang/StaticAnalyzer/Core/Checker.h
cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h
cfe/trunk/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp
cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
cfe/trunk/lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp
cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp
cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
cfe/trunk/test/Analysis/Inputs/system-header-simulator-for-simple-stream.h
cfe/trunk/test/Analysis/Inputs/system-header-simulator.h
cfe/trunk/test/Analysis/malloc.c
cfe/trunk/test/Analysis/simple-stream-checks.c
Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/Checker.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/Checker.h?rev=174677&r1=174676&r2=174677&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/Checker.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/Checker.h Thu Feb 7 17:05:43 2013
@@ -323,10 +323,12 @@ class PointerEscape {
_checkPointerEscape(void *checker,
ProgramStateRef State,
const InvalidatedSymbols &Escaped,
- const CallEvent *Call) {
+ const CallEvent *Call,
+ PointerEscapeKind Kind) {
return ((const CHECKER *)checker)->checkPointerEscape(State,
Escaped,
- Call);
+ Call,
+ Kind);
}
public:
Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h?rev=174677&r1=174676&r2=174677&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h Thu Feb 7 17:05:43 2013
@@ -112,6 +112,26 @@ public:
RET operator()() const { return Fn(Checker); }
};
+/// \brief Describes the different reasons a pointer escapes
+/// during analysis.
+enum PointerEscapeKind {
+ /// A pointer escapes due to binding its value to a location
+ /// that the analyzer cannot track.
+ PSK_EscapeOnBind,
+
+ /// The pointer has been passed to a function call directly.
+ PSK_DirectEscapeOnCall,
+
+ /// The pointer has been passed to a function indirectly.
+ /// For example, the pointer is accessible through an
+ /// argument to a function.
+ PSK_IndirectEscapeOnCall,
+
+ /// The reason for pointer escape is unknown. For example,
+ /// a region containing this pointer is invalidated.
+ PSK_EscapeOther
+};
+
class CheckerManager {
const LangOptions LangOpts;
@@ -330,7 +350,8 @@ public:
ProgramStateRef
runCheckersForPointerEscape(ProgramStateRef State,
const InvalidatedSymbols &Escaped,
- const CallEvent *Call);
+ const CallEvent *Call,
+ PointerEscapeKind Kind);
/// \brief Run checkers for handling assumptions on symbolic values.
ProgramStateRef runCheckersForEvalAssume(ProgramStateRef state,
@@ -420,7 +441,8 @@ public:
typedef CheckerFn<ProgramStateRef (ProgramStateRef,
const InvalidatedSymbols &Escaped,
- const CallEvent *Call)>
+ const CallEvent *Call,
+ PointerEscapeKind Kind)>
CheckPointerEscapeFunc;
typedef CheckerFn<ProgramStateRef (ProgramStateRef,
Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp?rev=174677&r1=174676&r2=174677&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp Thu Feb 7 17:05:43 2013
@@ -265,10 +265,12 @@ public:
/// \param Escaped The list of escaped symbols.
/// \param Call The corresponding CallEvent, if the symbols escape as
/// parameters to the given call.
+ /// \param Kind How the symbols have escaped.
/// \returns Checkers can modify the state by returning a new state.
ProgramStateRef checkPointerEscape(ProgramStateRef State,
const InvalidatedSymbols &Escaped,
- const CallEvent *Call) const {
+ const CallEvent *Call,
+ PointerEscapeKind Kind) const {
return State;
}
Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp?rev=174677&r1=174676&r2=174677&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp Thu Feb 7 17:05:43 2013
@@ -158,7 +158,8 @@ public:
ProgramStateRef checkPointerEscape(ProgramStateRef State,
const InvalidatedSymbols &Escaped,
- const CallEvent *Call) const;
+ const CallEvent *Call,
+ PointerEscapeKind Kind) const;
void printState(raw_ostream &Out, ProgramStateRef State,
const char *NL, const char *Sep) const;
@@ -1450,11 +1451,15 @@ bool MallocChecker::doesNotFreeMemory(co
ProgramStateRef MallocChecker::checkPointerEscape(ProgramStateRef State,
const InvalidatedSymbols &Escaped,
- const CallEvent *Call) const {
+ const CallEvent *Call,
+ PointerEscapeKind Kind) const {
// If we know that the call does not free memory, keep tracking the top
// level arguments.
- if (Call && doesNotFreeMemory(Call, State))
+ if ((Kind == PSK_DirectEscapeOnCall ||
+ Kind == PSK_IndirectEscapeOnCall) &&
+ doesNotFreeMemory(Call, State)) {
return State;
+ }
for (InvalidatedSymbols::const_iterator I = Escaped.begin(),
E = Escaped.end();
Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp?rev=174677&r1=174676&r2=174677&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp Thu Feb 7 17:05:43 2013
@@ -82,7 +82,8 @@ public:
/// Stop tracking addresses which escape.
ProgramStateRef checkPointerEscape(ProgramStateRef State,
const InvalidatedSymbols &Escaped,
- const CallEvent *Call) const;
+ const CallEvent *Call,
+ PointerEscapeKind Kind) const;
};
} // end anonymous namespace
@@ -255,10 +256,14 @@ bool SimpleStreamChecker::guaranteedNotT
ProgramStateRef
SimpleStreamChecker::checkPointerEscape(ProgramStateRef State,
const InvalidatedSymbols &Escaped,
- const CallEvent *Call) const {
+ const CallEvent *Call,
+ PointerEscapeKind Kind) const {
// If we know that the call cannot close a file, there is nothing to do.
- if (Call && guaranteedNotToCloseFile(*Call))
+ if ((Kind == PSK_DirectEscapeOnCall ||
+ Kind == PSK_IndirectEscapeOnCall) &&
+ guaranteedNotToCloseFile(*Call)) {
return State;
+ }
for (InvalidatedSymbols::const_iterator I = Escaped.begin(),
E = Escaped.end();
Modified: cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp?rev=174677&r1=174676&r2=174677&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp Thu Feb 7 17:05:43 2013
@@ -488,13 +488,19 @@ CheckerManager::runCheckersForRegionChan
ProgramStateRef
CheckerManager::runCheckersForPointerEscape(ProgramStateRef State,
const InvalidatedSymbols &Escaped,
- const CallEvent *Call) {
+ const CallEvent *Call,
+ PointerEscapeKind Kind) {
+ assert((Call != NULL ||
+ (Kind != PSK_DirectEscapeOnCall &&
+ Kind != PSK_IndirectEscapeOnCall)) &&
+ "Call must not be NULL when escaping on call");
+
for (unsigned i = 0, e = PointerEscapeCheckers.size(); i != e; ++i) {
// If any checker declares the state infeasible (or if it starts that way),
// bail out.
if (!State)
return NULL;
- State = PointerEscapeCheckers[i](State, Escaped, Call);
+ State = PointerEscapeCheckers[i](State, Escaped, Call, Kind);
}
return State;
}
Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=174677&r1=174676&r2=174677&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Thu Feb 7 17:05:43 2013
@@ -1648,7 +1648,8 @@ ProgramStateRef ExprEngine::processPoint
const InvalidatedSymbols &EscapedSymbols = Scanner.getSymbols();
State = getCheckerManager().runCheckersForPointerEscape(State,
EscapedSymbols,
- /*CallEvent*/ 0);
+ /*CallEvent*/ 0,
+ PSK_EscapeOnBind);
return State;
}
@@ -1665,7 +1666,9 @@ ExprEngine::processPointerEscapedOnInval
if (!Call)
return getCheckerManager().runCheckersForPointerEscape(State,
- *Invalidated, 0);
+ *Invalidated,
+ 0,
+ PSK_EscapeOther);
// If the symbols were invalidated by a call, we want to find out which ones
// were invalidated directly due to being arguments to the call.
@@ -1687,12 +1690,12 @@ ExprEngine::processPointerEscapedOnInval
if (!SymbolsDirectlyInvalidated.empty())
State = getCheckerManager().runCheckersForPointerEscape(State,
- SymbolsDirectlyInvalidated, Call);
+ SymbolsDirectlyInvalidated, Call, PSK_DirectEscapeOnCall);
// Notify about the symbols that get indirectly invalidated by the call.
if (!SymbolsIndirectlyInvalidated.empty())
State = getCheckerManager().runCheckersForPointerEscape(State,
- SymbolsIndirectlyInvalidated, /*CallEvent*/ 0);
+ SymbolsIndirectlyInvalidated, Call, PSK_IndirectEscapeOnCall);
return State;
}
Modified: cfe/trunk/test/Analysis/Inputs/system-header-simulator-for-simple-stream.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/Inputs/system-header-simulator-for-simple-stream.h?rev=174677&r1=174676&r2=174677&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/Inputs/system-header-simulator-for-simple-stream.h (original)
+++ cfe/trunk/test/Analysis/Inputs/system-header-simulator-for-simple-stream.h Thu Feb 7 17:05:43 2013
@@ -13,3 +13,9 @@ int fputc(int, FILE *);
int fputs(const char * restrict, FILE * restrict) __asm("_" "fputs" );
int fclose(FILE *);
void exit(int);
+
+// The following is a fake system header function
+typedef struct __FileStruct {
+ FILE * p;
+} FileStruct;
+void fakeSystemHeaderCall(FileStruct *);
Modified: cfe/trunk/test/Analysis/Inputs/system-header-simulator.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/Inputs/system-header-simulator.h?rev=174677&r1=174676&r2=174677&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/Inputs/system-header-simulator.h (original)
+++ cfe/trunk/test/Analysis/Inputs/system-header-simulator.h Thu Feb 7 17:05:43 2013
@@ -67,3 +67,11 @@ typedef void (*xpc_finalizer_t)(void *va
void xpc_connection_set_context(xpc_connection_t connection, void *context);
void xpc_connection_set_finalizer_f(xpc_connection_t connection, xpc_finalizer_t finalizer);
void xpc_connection_resume(xpc_connection_t connection);
+
+//The following is a fake system header function
+void fakeSystemHeaderCallInt(int *);
+
+typedef struct __SomeStruct {
+ char * p;
+} SomeStruct;
+void fakeSystemHeaderCall(SomeStruct *);
Modified: cfe/trunk/test/Analysis/malloc.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/malloc.c?rev=174677&r1=174676&r2=174677&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/malloc.c (original)
+++ cfe/trunk/test/Analysis/malloc.c Thu Feb 7 17:05:43 2013
@@ -13,6 +13,7 @@ void *reallocf(void *ptr, size_t size);
void *calloc(size_t nmemb, size_t size);
char *strdup(const char *s);
char *strndup(const char *s, size_t n);
+int memcmp(const void *s1, const void *s2, size_t n);
void myfoo(int *p);
void myfooint(int p);
@@ -1023,6 +1024,27 @@ char *testLeakWithinReturn(char *str) {
return strdup(strdup(str)); // expected-warning{{leak}}
}
+void passConstPtr(const char * ptr);
+
+void testPassConstPointer() {
+ char * string = malloc(sizeof(char)*10);
+ passConstPtr(string);
+ return; // expected-warning {{leak}}
+}
+
+void testPassConstPointerIndirectly() {
+ char *p = malloc(1);
+ p++;
+ memcmp(p, p, sizeof(&p));
+ return; // expected-warning {{leak}}
+}
+
+void testPassToSystemHeaderFunctionIndirectly() {
+ int *p = malloc(4);
+ p++;
+ fakeSystemHeaderCallInt(p);
+} // expected-warning {{leak}}
+
// ----------------------------------------------------------------------------
// False negatives.
@@ -1055,5 +1077,17 @@ void localStructTest() {
pSt->memP = malloc(12);
} // missing warning
+void testPassConstPointerIndirectlyStruct() {
+ struct HasPtr hp;
+ hp.p = malloc(10);
+ memcmp(&hp, &hp, sizeof(hp));
+ return; // missing leak
+}
+
+void testPassToSystemHeaderFunctionIndirectlyStruct() {
+ SomeStruct ss;
+ ss.p = malloc(1);
+ fakeSystemHeaderCall(&ss);
+} // missing leak
Modified: cfe/trunk/test/Analysis/simple-stream-checks.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/simple-stream-checks.c?rev=174677&r1=174676&r2=174677&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/simple-stream-checks.c (original)
+++ cfe/trunk/test/Analysis/simple-stream-checks.c Thu Feb 7 17:05:43 2013
@@ -76,3 +76,16 @@ void SymbolDoesNotEscapeThoughStringAPIs
fputc(*Data, F);
return; // expected-warning {{Opened file is never closed; potential resource leak}}
}
+
+void passConstPointer(const FILE * F);
+void testPassConstPointer() {
+ FILE *F = fopen("myfile.txt", "w");
+ passConstPointer(F);
+ return; // expected-warning {{Opened file is never closed; potential resource leak}}
+}
+
+void testPassToSystemHeaderFunctionIndirectly() {
+ FileStruct fs;
+ fs.p = fopen("myfile.txt", "w");
+ fakeSystemHeaderCall(&fs);
+} // expected leak warning
More information about the cfe-commits
mailing list