r314910 - [analyzer] Fix autodetection of binding types.
Artem Dergachev via cfe-commits
cfe-commits at lists.llvm.org
Wed Oct 4 08:59:40 PDT 2017
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}}
+}
More information about the cfe-commits
mailing list