summaryrefslogtreecommitdiffstats
path: root/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
diff options
context:
space:
mode:
authorAnna Zaks <ganna@apple.com>2012-06-20 20:57:46 +0000
committerAnna Zaks <ganna@apple.com>2012-06-20 20:57:46 +0000
commit9050ffd57c9f88a9a660f9605659fa9ee40c9281 (patch)
treeae6d65956e2074c689d3d227d85e6023637860ad /clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
parent51b7357159d7d28e01e341b5192d8d09abd7a7ad (diff)
downloadbcm5719-llvm-9050ffd57c9f88a9a660f9605659fa9ee40c9281.tar.gz
bcm5719-llvm-9050ffd57c9f88a9a660f9605659fa9ee40c9281.zip
[analyzer] Malloc: cleanup, disallow free on relinquished memory.
This commits sets the grounds for more aggressive use after free checking. We will use the Relinquished sate to denote that someone else is now responsible for releasing the memory. llvm-svn: 158850
Diffstat (limited to 'clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp')
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp27
1 files changed, 17 insertions, 10 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
index 255225467f0..48fdec2d3f9 100644
--- a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
@@ -34,15 +34,24 @@ using namespace ento;
namespace {
class RefState {
- enum Kind { AllocateUnchecked, AllocateFailed, Released, Escaped,
+ enum Kind { // Reference to allocated memory.
+ Allocated,
+ // Reference to released/freed memory.
+ Released,
+ // Reference to escaped memory - no assumptions can be made of
+ // the state after the reference escapes.
+ Escaped,
+ // The responsibility for freeing resources has transfered from
+ // this reference. A relinquished symbol should not be freed.
Relinquished } K;
const Stmt *S;
public:
RefState(Kind k, const Stmt *s) : K(k), S(s) {}
- bool isAllocated() const { return K == AllocateUnchecked; }
+ bool isAllocated() const { return K == Allocated; }
bool isReleased() const { return K == Released; }
+ bool isRelinquished() const { return K == Relinquished; }
const Stmt *getStmt() const { return S; }
@@ -50,11 +59,8 @@ public:
return K == X.K && S == X.S;
}
- static RefState getAllocateUnchecked(const Stmt *s) {
- return RefState(AllocateUnchecked, s);
- }
- static RefState getAllocateFailed() {
- return RefState(AllocateFailed, 0);
+ static RefState getAllocated(const Stmt *s) {
+ return RefState(Allocated, s);
}
static RefState getReleased(const Stmt *s) { return RefState(Released, s); }
static RefState getEscaped(const Stmt *s) { return RefState(Escaped, s); }
@@ -528,7 +534,7 @@ ProgramStateRef MallocChecker::MallocUpdateRefState(CheckerContext &C,
assert(Sym);
// Set the symbol's state to Allocated.
- return state->set<RegionState>(Sym, RefState::getAllocateUnchecked(CE));
+ return state->set<RegionState>(Sym, RefState::getAllocated(CE));
}
@@ -628,7 +634,8 @@ ProgramStateRef MallocChecker::FreeMemAux(CheckerContext &C,
return 0;
// Check double free.
- if (RS->isReleased()) {
+ // TODO: Split the 2 cases for better error messages.
+ if (RS->isReleased() || RS->isRelinquished()) {
if (ExplodedNode *N = C.generateSink()) {
if (!BT_DoubleFree)
BT_DoubleFree.reset(
@@ -1237,7 +1244,7 @@ ProgramStateRef MallocChecker::evalAssume(ProgramStateRef state,
if (RS) {
if (RS->isReleased() && ! I.getData().IsFreeOnFailure)
state = state->set<RegionState>(ReallocSym,
- RefState::getAllocateUnchecked(RS->getStmt()));
+ RefState::getAllocated(RS->getStmt()));
}
state = state->remove<ReallocPairs>(I.getKey());
}
OpenPOWER on IntegriCloud