From: Jordan Rose Date: Wed, 23 Oct 2013 20:08:55 +0000 (+0000) Subject: [analyzer] Generate a LazyCompoundVal when loading from a union-typed region. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=1dc31f5ead63d7197edf6f34a7821b93ea6698a1;p=clang [analyzer] Generate a LazyCompoundVal when loading from a union-typed region. 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 --- diff --git a/lib/StaticAnalyzer/Core/RegionStore.cpp b/lib/StaticAnalyzer/Core/RegionStore.cpp index 3cf1e5acde..0b519768aa 100644 --- a/lib/StaticAnalyzer/Core/RegionStore.cpp +++ b/lib/StaticAnalyzer/Core/RegionStore.cpp @@ -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(R)) { diff --git a/test/Analysis/unions.cpp b/test/Analysis/unions.cpp index 2bffe78b41..f363ab81ae 100644 --- a/test/Analysis/unions.cpp +++ b/test/Analysis/unions.cpp @@ -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}} + } +}