From: Anna Zaks Date: Thu, 22 Mar 2012 00:57:20 +0000 (+0000) Subject: [analyzer] Malloc: drop symbols captured by blocks. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f5aa3f5e58356d0bea823fe75dd7bf6aea6f47f4;p=clang [analyzer] Malloc: drop symbols captured by blocks. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@153232 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp index 65a6aacc67..502fb1ed75 100644 --- a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -89,6 +89,7 @@ class MallocChecker : public Checker, check::PreStmt, check::PostStmt, + check::PostStmt, check::Location, check::Bind, eval::Assume, @@ -116,6 +117,7 @@ public: void checkPreStmt(const CallExpr *S, CheckerContext &C) const; void checkPostStmt(const CallExpr *CE, CheckerContext &C) const; + void checkPostStmt(const BlockExpr *BE, CheckerContext &C) const; void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const; void checkEndPath(CheckerContext &C) const; void checkPreStmt(const ReturnStmt *S, CheckerContext &C) const; @@ -1008,6 +1010,46 @@ void MallocChecker::checkPreStmt(const ReturnStmt *S, CheckerContext &C) const { checkEscape(Sym, E, C); } +// TODO: Blocks should be either inlined or should call invalidate regions +// upon invocation. After that's in place, special casing here will not be +// needed. +void MallocChecker::checkPostStmt(const BlockExpr *BE, + CheckerContext &C) const { + + // Scan the BlockDecRefExprs for any object the retain count checker + // may be tracking. + if (!BE->getBlockDecl()->hasCaptures()) + return; + + ProgramStateRef state = C.getState(); + const BlockDataRegion *R = + cast(state->getSVal(BE, + C.getLocationContext()).getAsRegion()); + + BlockDataRegion::referenced_vars_iterator I = R->referenced_vars_begin(), + E = R->referenced_vars_end(); + + if (I == E) + return; + + SmallVector Regions; + const LocationContext *LC = C.getLocationContext(); + MemRegionManager &MemMgr = C.getSValBuilder().getRegionManager(); + + for ( ; I != E; ++I) { + const VarRegion *VR = *I; + if (VR->getSuperRegion() == R) { + VR = MemMgr.getVarRegion(VR->getDecl(), LC); + } + Regions.push_back(VR); + } + + state = + state->scanReachableSymbols(Regions.data(), + Regions.data() + Regions.size()).getState(); + C.addTransition(state); +} + bool MallocChecker::checkUseAfterFree(SymbolRef Sym, CheckerContext &C, const Stmt *S) const { assert(Sym); diff --git a/test/Analysis/malloc.mm b/test/Analysis/malloc.mm index 31db5ced15..4cb2cfa328 100644 --- a/test/Analysis/malloc.mm +++ b/test/Analysis/malloc.mm @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc -analyzer-store=region -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc -analyzer-store=region -verify -fblocks %s #include "system-header-simulator-objc.h" typedef __typeof(sizeof(int)) size_t; @@ -97,3 +97,12 @@ NSData *radar10976702() { return [NSData dataWithBytesNoCopy:bytes length:10]; // no-warning } +void testBlocks() { + int *x= (int*)malloc(sizeof(int)); + int (^myBlock)(int) = ^(int num) { + free(x); + return num; + }; + myBlock(3); +} +