Author: dergachev Date: Wed Oct 4 08:59:40 2017 New Revision: 314910 URL: http://llvm.org/viewvc/llvm-project?rev=314910&view=rev Log: [analyzer] Fix autodetection of binding types.
In ProgramState::getSVal(Location, Type) API which dereferences a pointer value, when the optional Type parameter is not supplied and the Location is not typed, type should have been guessed on a best-effort basis by inspecting the Location more deeply. However, this never worked; the auto-detected type was instead a pointer type to the correct type. Fixed the issue and added various test cases to demonstrate which parts of the analyzer were affected (uninitialized pointer argument checker, C++ trivial copy modeling, Google test API modeling checker). Additionally, autodetected void types are automatically replaced with char, in order to simplify checker APIs. Which means that if the location is a void pointer, getSVal() would read the first byte through this pointer and return its symbolic value. Fixes pr34305. Differential Revision: https://reviews.llvm.org/D38358 Modified: cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp cfe/trunk/test/Analysis/ctor.mm cfe/trunk/test/Analysis/exercise-ps.c cfe/trunk/test/Analysis/gtest.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp?rev=314910&r1=314909&r2=314910&view=diff ============================================================================== --- cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp Wed Oct 4 08:59:40 2017 @@ -1393,16 +1393,19 @@ SVal RegionStoreManager::getBinding(Regi return UnknownVal(); } - if (isa<AllocaRegion>(MR) || - isa<SymbolicRegion>(MR) || - isa<CodeTextRegion>(MR)) { + if (!isa<TypedValueRegion>(MR)) { if (T.isNull()) { if (const TypedRegion *TR = dyn_cast<TypedRegion>(MR)) - T = TR->getLocationType(); - else { - const SymbolicRegion *SR = cast<SymbolicRegion>(MR); - T = SR->getSymbol()->getType(); - } + T = TR->getLocationType()->getPointeeType(); + else if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(MR)) + T = SR->getSymbol()->getType()->getPointeeType(); + else if (isa<AllocaRegion>(MR)) + T = Ctx.VoidTy; + } + assert(!T.isNull() && "Unable to auto-detect binding type!"); + if (T->isVoidType()) { + // When trying to dereference a void pointer, read the first byte. + T = Ctx.CharTy; } MR = GetElementZeroRegion(cast<SubRegion>(MR), T); } Modified: cfe/trunk/test/Analysis/ctor.mm URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/ctor.mm?rev=314910&r1=314909&r2=314910&view=diff ============================================================================== --- cfe/trunk/test/Analysis/ctor.mm (original) +++ cfe/trunk/test/Analysis/ctor.mm Wed Oct 4 08:59:40 2017 @@ -199,7 +199,7 @@ namespace PODUninitialized { Inner p; }; - void testPOD() { + void testPOD(const POD &pp) { POD p; p.x = 1; POD p2 = p; // no-warning @@ -210,6 +210,15 @@ namespace PODUninitialized { // Use rvalues as well. clang_analyzer_eval(POD(p3).x == 1); // expected-warning{{TRUE}} + // Copy from symbolic references correctly. + POD p4 = pp; + // Make sure that p4.x contains a symbol after copy. + if (p4.x > 0) + clang_analyzer_eval(p4.x > 0); // expected-warning{{TRUE}} + // FIXME: Element region gets in the way, so these aren't the same symbols + // as they should be. + clang_analyzer_eval(pp.x == p4.x); // expected-warning{{UNKNOWN}} + PODWrapper w; w.p.y = 1; PODWrapper w2 = w; // no-warning Modified: cfe/trunk/test/Analysis/exercise-ps.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/exercise-ps.c?rev=314910&r1=314909&r2=314910&view=diff ============================================================================== --- cfe/trunk/test/Analysis/exercise-ps.c (original) +++ cfe/trunk/test/Analysis/exercise-ps.c Wed Oct 4 08:59:40 2017 @@ -21,3 +21,11 @@ static void f2(void *buf) { memcpy((&x[1]), (buf), 1); // expected-warning{{implicitly declaring library function 'memcpy' with type 'void *(void *, const void *}} \ // expected-note{{include the header <string.h> or explicitly provide a declaration for 'memcpy'}} } + +// AllocaRegion is untyped. Void pointer isn't of much help either. Before +// realizing that the value is undefined, we need to somehow figure out +// what type of value do we expect. +void f3(void *dest) { + void *src = __builtin_alloca(5); + memcpy(dest, src, 1); // expected-warning{{2nd function call argument is a pointer to uninitialized value}} +} Modified: cfe/trunk/test/Analysis/gtest.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/gtest.cpp?rev=314910&r1=314909&r2=314910&view=diff ============================================================================== --- cfe/trunk/test/Analysis/gtest.cpp (original) +++ cfe/trunk/test/Analysis/gtest.cpp Wed Oct 4 08:59:40 2017 @@ -151,3 +151,17 @@ void testConstrainState(int p) { ASSERT_TRUE(false); clang_analyzer_warnIfReached(); // no-warning } + +void testAssertSymbolicPtr(const bool *b) { + ASSERT_TRUE(*b); // no-crash + + // FIXME: Our solver doesn't handle this well yet. + clang_analyzer_eval(*b); // expected-warning{{UNKNOWN}} +} + +void testAssertSymbolicRef(const bool &b) { + ASSERT_TRUE(b); // no-crash + + // FIXME: Our solver doesn't handle this well yet. + clang_analyzer_eval(b); // expected-warning{{UNKNOWN}} +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits