]> granicus.if.org Git - clang/commitdiff
[analyzer] teach analyzer about ObjC literals, thus trimming out a false positive...
authorTed Kremenek <kremenek@apple.com>
Tue, 28 Feb 2012 00:56:05 +0000 (00:56 +0000)
committerTed Kremenek <kremenek@apple.com>
Tue, 28 Feb 2012 00:56:05 +0000 (00:56 +0000)
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

include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
lib/StaticAnalyzer/Core/Environment.cpp
lib/StaticAnalyzer/Core/MemRegion.cpp
lib/StaticAnalyzer/Core/Store.cpp
test/Analysis/malloc.m [new file with mode: 0644]

index c440ef0469e2211ad7cc1c5eeffc9e24b850da2f..420231ad0e3dc16ab44714371b68842616312f87 100644 (file)
@@ -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.
index a44476e850c41dd279731cc91f1ce9b70c1c954d..5207a506aec9617de532450d409480009d80a1fd 100644 (file)
@@ -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);
index e08a64156894ff68a29b5dab60879e4edeb07e36..d63ec94c299923691b04ba24a0f74bfbc868fcad 100644 (file)
@@ -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;
index 1abac09c8f964cd8641d1a6b7058b04beaf392ec..acf5e193ab3f53f91e5406ac8b92597daed66ed5 100644 (file)
@@ -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 (file)
index 0000000..6451dbc
--- /dev/null
@@ -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
+