From bb61c8cc739bc29ea9d15a1b486273eb98023321 Mon Sep 17 00:00:00 2001 From: Jordan Rose Date: Wed, 23 Oct 2013 20:08:55 +0000 Subject: [PATCH] [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 llvm-svn: 193265 --- clang/lib/StaticAnalyzer/Core/RegionStore.cpp | 4 +- clang/test/Analysis/unions.cpp | 61 ++++++++++++++++++- 2 files changed, 62 insertions(+), 3 deletions(-) diff --git a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp index 3cf1e5acde95..0b519768aa04 100644 --- a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp +++ b/clang/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/clang/test/Analysis/unions.cpp b/clang/test/Analysis/unions.cpp index 2bffe78b41c2..f363ab81ae72 100644 --- a/clang/test/Analysis/unions.cpp +++ b/clang/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}} + } +}