diff options
author | Ted Kremenek <kremenek@apple.com> | 2012-02-28 00:56:05 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2012-02-28 00:56:05 +0000 |
commit | 4c62b557e269a27515dfca1f754ae936c8fdb824 (patch) | |
tree | 55227ce5bd531fbc28d09fdc1451962672b2108d | |
parent | 033d3007b16d7f6c0f0eafd06c7096cfd22d89f5 (diff) |
[analyzer] teach analyzer about ObjC literals, thus trimming out a false positive with the malloc() checker involving
comparing literal addresses to nil.
Fixes <rdar://problem/10579586>
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@151602 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h | 40 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/Environment.cpp | 5 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/MemRegion.cpp | 17 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/Store.cpp | 1 | ||||
-rw-r--r-- | test/Analysis/malloc.m | 37 |
5 files changed, 99 insertions, 1 deletions
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h index c440ef0469..420231ad0e 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h @@ -18,6 +18,7 @@ #include "clang/AST/CharUnits.h" #include "clang/AST/Decl.h" +#include "clang/AST/ExprObjC.h" #include "clang/Basic/LLVM.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" #include "llvm/Support/ErrorHandling.h" @@ -94,6 +95,7 @@ public: CompoundLiteralRegionKind = BEG_TYPED_VALUE_REGIONS, CXXThisRegionKind, StringRegionKind, + ObjCStringRegionKind, ElementRegionKind, // Decl Regions. BEG_DECL_REGIONS, @@ -694,6 +696,40 @@ public: return R->getKind() == StringRegionKind; } }; + +/// The region associated with an ObjCStringLiteral. +class ObjCStringRegion : public TypedValueRegion { + friend class MemRegionManager; + const ObjCStringLiteral* Str; +protected: + + ObjCStringRegion(const ObjCStringLiteral* str, const MemRegion* sreg) + : TypedValueRegion(sreg, ObjCStringRegionKind), Str(str) {} + + static void ProfileRegion(llvm::FoldingSetNodeID& ID, + const ObjCStringLiteral* Str, + const MemRegion* superRegion); + +public: + + const ObjCStringLiteral* getObjCStringLiteral() const { return Str; } + + QualType getValueType() const { + return Str->getType(); + } + + bool isBoundable() const { return false; } + + void Profile(llvm::FoldingSetNodeID& ID) const { + ProfileRegion(ID, Str, superRegion); + } + + void dumpToStream(raw_ostream &os) const; + + static bool classof(const MemRegion* R) { + return R->getKind() == ObjCStringRegionKind; + } +}; /// CompoundLiteralRegion - A memory region representing a compound literal. /// Compound literals are essentially temporaries that are stack allocated @@ -1067,7 +1103,9 @@ public: /// getSymbolicRegion - Retrieve or create a "symbolic" memory region. const SymbolicRegion* getSymbolicRegion(SymbolRef sym); - const StringRegion* getStringRegion(const StringLiteral* Str); + const StringRegion *getStringRegion(const StringLiteral* Str); + + const ObjCStringRegion *getObjCStringRegion(const ObjCStringLiteral *Str); /// getVarRegion - Retrieve or create the memory region associated with /// a specified VarDecl and LocationContext. diff --git a/lib/StaticAnalyzer/Core/Environment.cpp b/lib/StaticAnalyzer/Core/Environment.cpp index a44476e850..5207a506ae 100644 --- a/lib/StaticAnalyzer/Core/Environment.cpp +++ b/lib/StaticAnalyzer/Core/Environment.cpp @@ -90,6 +90,11 @@ SVal Environment::getSVal(const EnvironmentEntry &Entry, continue; case Stmt::ObjCPropertyRefExprClass: return loc::ObjCPropRef(cast<ObjCPropertyRefExpr>(E)); + case Stmt::ObjCStringLiteralClass: { + MemRegionManager &MRMgr = svalBuilder.getRegionManager(); + const ObjCStringLiteral *SL = cast<ObjCStringLiteral>(E); + return svalBuilder.makeLoc(MRMgr.getObjCStringRegion(SL)); + } case Stmt::StringLiteralClass: { MemRegionManager &MRMgr = svalBuilder.getRegionManager(); const StringLiteral *SL = cast<StringLiteral>(E); diff --git a/lib/StaticAnalyzer/Core/MemRegion.cpp b/lib/StaticAnalyzer/Core/MemRegion.cpp index e08a641568..d63ec94c29 100644 --- a/lib/StaticAnalyzer/Core/MemRegion.cpp +++ b/lib/StaticAnalyzer/Core/MemRegion.cpp @@ -262,6 +262,14 @@ void StringRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, ID.AddPointer(superRegion); } +void ObjCStringRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, + const ObjCStringLiteral* Str, + const MemRegion* superRegion) { + ID.AddInteger((unsigned) ObjCStringRegionKind); + ID.AddPointer(Str); + ID.AddPointer(superRegion); +} + void AllocaRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, const Expr *Ex, unsigned cnt, const MemRegion *) { @@ -486,6 +494,10 @@ void StringRegion::dumpToStream(raw_ostream &os) const { Str->printPretty(os, 0, PrintingPolicy(getContext().getLangOptions())); } +void ObjCStringRegion::dumpToStream(raw_ostream &os) const { + Str->printPretty(os, 0, PrintingPolicy(getContext().getLangOptions())); +} + void SymbolicRegion::dumpToStream(raw_ostream &os) const { os << "SymRegion{" << sym << '}'; } @@ -613,6 +625,11 @@ const StringRegion* MemRegionManager::getStringRegion(const StringLiteral* Str){ return getSubRegion<StringRegion>(Str, getGlobalsRegion()); } +const ObjCStringRegion * +MemRegionManager::getObjCStringRegion(const ObjCStringLiteral* Str){ + return getSubRegion<ObjCStringRegion>(Str, getGlobalsRegion()); +} + const VarRegion* MemRegionManager::getVarRegion(const VarDecl *D, const LocationContext *LC) { const MemRegion *sReg = 0; diff --git a/lib/StaticAnalyzer/Core/Store.cpp b/lib/StaticAnalyzer/Core/Store.cpp index 1abac09c8f..acf5e193ab 100644 --- a/lib/StaticAnalyzer/Core/Store.cpp +++ b/lib/StaticAnalyzer/Core/Store.cpp @@ -120,6 +120,7 @@ const MemRegion *StoreManager::castRegion(const MemRegion *R, QualType CastToTy) case MemRegion::CompoundLiteralRegionKind: case MemRegion::FieldRegionKind: case MemRegion::ObjCIvarRegionKind: + case MemRegion::ObjCStringRegionKind: case MemRegion::VarRegionKind: case MemRegion::CXXTempObjectRegionKind: case MemRegion::CXXBaseObjectRegionKind: diff --git a/test/Analysis/malloc.m b/test/Analysis/malloc.m new file mode 100644 index 0000000000..6451dbc983 --- /dev/null +++ b/test/Analysis/malloc.m @@ -0,0 +1,37 @@ +// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc -analyzer-store=region -verify %s +#include "system-header-simulator-objc.h" + +@class NSString; +typedef __typeof(sizeof(int)) size_t; +void *malloc(size_t); +void free(void *); + +// RDar10579586 - Test use of malloc() with Objective-C string literal as a +// test condition. Not really a malloc() issue, but this also exercises +// the check that malloc() returns uninitialized memory. +@interface RDar10579586 +struct rdar0579586_str { + char str_c; +}; +@end + +void rdar10579586(char x); + +@implementation RDar10579586 ++ (NSString *)foobar +{ + struct rdar0579586_str *buffer = ((void*)0); + NSString *error = ((void*)0); + + if ((buffer = malloc(sizeof(struct rdar0579586_str))) == ((void*)0)) + error = @"buffer allocation failure"; + + if (error != ((void*)0)) + return error; + + rdar10579586(buffer->str_c); // expected-warning {{Function call argument is an uninitialized value}} + free(buffer); + return ((void*)0); +} +@end + |