]> granicus.if.org Git - clang/commitdiff
[analyzer] Generate a LazyCompoundVal when loading from a union-typed region.
authorJordan Rose <jordan_rose@apple.com>
Wed, 23 Oct 2013 20:08:55 +0000 (20:08 +0000)
committerJordan Rose <jordan_rose@apple.com>
Wed, 23 Oct 2013 20:08:55 +0000 (20:08 +0000)
This ensures that variables accessible through a union are invalidated when
the union value is passed to a function. We still don't fully handle union
values, but this should at least quiet some false positives.

PR16596

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@193265 91177308-0d34-0410-b5e6-96231b3b80d8

lib/StaticAnalyzer/Core/RegionStore.cpp
test/Analysis/unions.cpp

index 3cf1e5acde9521dfed083b206b33be84c93a59ee..0b519768aa0494b3bd23e1e26f15753a7d8d6b4f 100644 (file)
@@ -1312,7 +1312,7 @@ SVal RegionStoreManager::getBinding(RegionBindingsConstRef B, Loc L, QualType T)
 
   // FIXME: Handle unions.
   if (RTy->isUnionType())
-    return UnknownVal();
+    return createLazyBinding(B, R);
 
   if (RTy->isArrayType()) {
     if (RTy->isConstantArrayType())
@@ -1906,6 +1906,8 @@ RegionStoreManager::bind(RegionBindingsConstRef B, Loc L, SVal V) {
       return bindStruct(B, TR, V);
     if (Ty->isVectorType())
       return bindVector(B, TR, V);
+    if (Ty->isUnionType())
+      return bindAggregate(B, TR, V);
   }
 
   if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R)) {
index 2bffe78b41c25b12745443629e363e0e661767a2..f363ab81ae7259a98092b9ecc757fc1e637d207f 100644 (file)
@@ -1,5 +1,7 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=core %s -verify
-// expected-no-diagnostics
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,debug.ExprInspection %s -verify
+
+extern void clang_analyzer_eval(bool);
+extern "C" char *strdup(const char *s);
 
 namespace PR14054_reduced {
   struct Definition;
@@ -49,3 +51,58 @@ namespace PR14054_original {
     x = pn->pn_u.name.lexdef->pn_u.name.lexdef;
   }
 }
+
+namespace PR17596 {
+  union IntOrString {
+    int i;
+    char *s;
+  };
+
+  extern void process(IntOrString);
+
+  void test() {
+    IntOrString uu;
+    uu.s = strdup("");
+    process(uu);
+  }
+
+  void testPositive() {
+    IntOrString uu;
+    uu.s = strdup("");
+  } // expected-warning{{leak}}
+
+  void testCopy() {
+    IntOrString uu;
+    uu.i = 4;
+    clang_analyzer_eval(uu.i == 4); // expected-warning{{TRUE}}
+
+    IntOrString vv;
+    vv.i = 5;
+    uu = vv;
+    // FIXME: Should be true.
+    clang_analyzer_eval(uu.i == 5); // expected-warning{{UNKNOWN}}
+  }
+
+  void testInvalidation() {
+    IntOrString uu;
+    uu.s = strdup("");
+
+    IntOrString vv;
+    char str[] = "abc";
+    vv.s = str;
+
+    // FIXME: This is a leak of uu.s.
+    uu = vv;
+  }
+
+  void testIndirectInvalidation() {
+    IntOrString uu;
+    char str[] = "abc";
+    uu.s = str;
+
+    clang_analyzer_eval(uu.s[0] == 'a'); // expected-warning{{TRUE}}
+
+    process(uu);
+    clang_analyzer_eval(uu.s[0] == 'a'); // expected-warning{{UNKNOWN}}
+  }
+}