r368773 - [analyzer] Track the right hand side of the last store regardless of its value
Kristof Umann via cfe-commits
cfe-commits at lists.llvm.org
Tue Aug 13 16:48:10 PDT 2019
Author: szelethus
Date: Tue Aug 13 16:48:10 2019
New Revision: 368773
URL: http://llvm.org/viewvc/llvm-project?rev=368773&view=rev
Log:
[analyzer] Track the right hand side of the last store regardless of its value
Summary:
The following code snippet taken from D64271#1572188 has an issue: namely,
because `flag`'s value isn't undef or a concrete int, it isn't being tracked.
int flag;
bool coin();
void foo() {
flag = coin();
}
void test() {
int *x = 0;
int local_flag;
flag = 1;
foo();
local_flag = flag;
if (local_flag)
x = new int;
foo();
local_flag = flag;
if (local_flag)
*x = 5;
}
This, in my opinion, makes no sense, other values may be interesting too.
Originally added by rC185608.
Differential Revision: https://reviews.llvm.org/D64287
Modified:
cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
cfe/trunk/test/Analysis/track-control-dependency-conditions.cpp
cfe/trunk/test/Analysis/uninit-const.c
cfe/trunk/test/Analysis/uninit-const.cpp
Modified: cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp?rev=368773&r1=368772&r2=368773&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp Tue Aug 13 16:48:10 2019
@@ -1394,15 +1394,11 @@ FindLastStoreBRVisitor::VisitNode(const
// If we have an expression that provided the value, try to track where it
// came from.
if (InitE) {
- if (V.isUndef() ||
- V.getAs<loc::ConcreteInt>() || V.getAs<nonloc::ConcreteInt>()) {
- if (!IsParam)
- InitE = InitE->IgnoreParenCasts();
- bugreporter::trackExpressionValue(StoreSite, InitE, BR,
- EnableNullFPSuppression);
- }
- ReturnVisitor::addVisitorIfNecessary(StoreSite, InitE->IgnoreParenCasts(),
- BR, EnableNullFPSuppression);
+ if (!IsParam)
+ InitE = InitE->IgnoreParenCasts();
+
+ bugreporter::trackExpressionValue(StoreSite, InitE, BR,
+ EnableNullFPSuppression);
}
// Okay, we've found the binding. Emit an appropriate message.
@@ -1945,19 +1941,20 @@ bool bugreporter::trackExpressionValue(c
// We should not try to dereference pointers at all when we don't care
// what is written inside the pointer.
bool CanDereference = true;
- if (const auto *SR = dyn_cast<SymbolicRegion>(L->getRegion()))
+ if (const auto *SR = L->getRegionAs<SymbolicRegion>()) {
if (SR->getSymbol()->getType()->getPointeeType()->isVoidType())
CanDereference = false;
+ } else if (const auto *AR = L->getRegionAs<AllocaRegion>())
+ CanDereference = false;
// At this point we are dealing with the region's LValue.
// However, if the rvalue is a symbolic region, we should track it as well.
// Try to use the correct type when looking up the value.
SVal RVal;
- if (ExplodedGraph::isInterestingLValueExpr(Inner)) {
+ if (ExplodedGraph::isInterestingLValueExpr(Inner))
RVal = LVState->getRawSVal(L.getValue(), Inner->getType());
- } else if (CanDereference) {
+ else if (CanDereference)
RVal = LVState->getSVal(L->getRegion());
- }
if (CanDereference)
if (auto KV = RVal.getAs<KnownSVal>())
Modified: cfe/trunk/test/Analysis/track-control-dependency-conditions.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/track-control-dependency-conditions.cpp?rev=368773&r1=368772&r2=368773&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/track-control-dependency-conditions.cpp (original)
+++ cfe/trunk/test/Analysis/track-control-dependency-conditions.cpp Tue Aug 13 16:48:10 2019
@@ -366,6 +366,30 @@ void f(int y) {
}
} // end of namespace tracked_condition_written_in_nested_stackframe
+namespace condition_written_in_nested_stackframe_before_assignment {
+int flag = 0;
+int getInt();
+
+void foo() {
+ flag = getInt(); // tracking-note{{Value assigned to 'flag'}}
+}
+
+void f() {
+ int *x = 0; // expected-note{{'x' initialized to a null pointer value}}
+ int y = 0;
+
+ foo(); // tracking-note{{Calling 'foo'}}
+ // tracking-note at -1{{Returning from 'foo'}}
+ y = flag; // tracking-note{{Value assigned to 'y'}}
+
+ if (y) // expected-note{{Assuming 'y' is not equal to 0}}
+ // expected-note at -1{{Taking true branch}}
+ // debug-note at -2{{Tracking condition 'y'}}
+ *x = 5; // expected-warning{{Dereference of null pointer}}
+ // expected-note at -1{{Dereference of null pointer}}
+}
+} // end of namespace condition_written_in_nested_stackframe_before_assignment
+
namespace collapse_point_not_in_condition {
[[noreturn]] void halt();
Modified: cfe/trunk/test/Analysis/uninit-const.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/uninit-const.c?rev=368773&r1=368772&r2=368773&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/uninit-const.c (original)
+++ cfe/trunk/test/Analysis/uninit-const.c Tue Aug 13 16:48:10 2019
@@ -24,15 +24,15 @@ void doStuff_constStaticSizedArray(const
void doStuff_variadic(const int *u, ...){};
void f_1(void) {
- int t;
+ int t; // expected-note {{'t' declared without an initial value}}
int* tp = &t; // expected-note {{'tp' initialized here}}
doStuff_pointerToConstInt(tp); // expected-warning {{1st function call argument is a pointer to uninitialized value}}
// expected-note at -1 {{1st function call argument is a pointer to uninitialized value}}
}
void f_1_1(void) {
- int t;
- int* tp1 = &t;
+ int t; // expected-note {{'t' declared without an initial value}}
+ int *tp1 = &t; // expected-note {{'tp1' initialized here}}
int* tp2 = tp1; // expected-note {{'tp2' initialized here}}
doStuff_pointerToConstInt(tp2); // expected-warning {{1st function call argument is a pointer to uninitialized value}}
// expected-note at -1 {{1st function call argument is a pointer to uninitialized value}}
@@ -40,12 +40,15 @@ void f_1_1(void) {
int *f_2_sub(int *p) {
- return p;
+ return p; // expected-note {{Returning pointer (loaded from 'p')}}
}
void f_2(void) {
- int t;
- int* p = f_2_sub(&t);
+ int t; // expected-note {{'t' declared without an initial value}}
+ int *p = f_2_sub(&t); // expected-note {{Passing value via 1st parameter 'p'}}
+ // expected-note at -1{{Calling 'f_2_sub'}}
+ // expected-note at -2{{Returning from 'f_2_sub'}}
+ // expected-note at -3{{'p' initialized here}}
int* tp = p; // expected-note {{'tp' initialized here}}
doStuff_pointerToConstInt(tp); // expected-warning {{1st function call argument is a pointer to uninitialized value}}
// expected-note at -1 {{1st function call argument is a pointer to uninitialized value}}
@@ -62,7 +65,7 @@ void f_4(void) {
}
void f_5(void) {
- int ta[5];
+ int ta[5]; // expected-note {{'ta' initialized here}}
int* tp = ta; // expected-note {{'tp' initialized here}}
doStuff_pointerToConstInt(tp); // expected-warning {{1st function call argument is a pointer to uninitialized value}}
// expected-note at -1 {{1st function call argument is a pointer to uninitialized value}}
@@ -99,7 +102,7 @@ void f_8(void) {
}
void f_9(void) {
- int a[6];
+ int a[6]; // expected-note {{'a' initialized here}}
int const *ptau = a; // expected-note {{'ptau' initialized here}}
doStuff_arrayOfConstInt(ptau); // expected-warning {{1st function call argument is a pointer to uninitialized value}}
// expected-note at -1 {{1st function call argument is a pointer to uninitialized value}}
@@ -173,7 +176,7 @@ int f_malloc_2(void) {
// uninit pointer, uninit val
void f_variadic_unp_unv(void) {
- int t;
+ int t; // expected-note {{'t' declared without an initial value}}
int v;
int* tp = &t; // expected-note {{'tp' initialized here}}
doStuff_variadic(tp,v); // expected-warning {{1st function call argument is a pointer to uninitialized value}}
@@ -181,7 +184,7 @@ void f_variadic_unp_unv(void) {
}
// uninit pointer, init val
void f_variadic_unp_inv(void) {
- int t;
+ int t; // expected-note {{'t' declared without an initial value}}
int v = 3;
int* tp = &t; // expected-note {{'tp' initialized here}}
doStuff_variadic(tp,v); // expected-warning {{1st function call argument is a pointer to uninitialized value}}
@@ -216,7 +219,7 @@ void f_variadic_inp_inp(void) {
//uninit pointer, init pointer
void f_variadic_unp_inp(void) {
- int t;
+ int t; // expected-note {{'t' declared without an initial value}}
int u=3;
int *vp = &u ;
int *tp = &t; // expected-note {{'tp' initialized here}}
@@ -235,7 +238,7 @@ void f_variadic_inp_unp(void) {
//uninit pointer, uninit pointer
void f_variadic_unp_unp(void) {
- int t;
+ int t; // expected-note {{'t' declared without an initial value}}
int u;
int *vp = &u ;
int *tp = &t; // expected-note {{'tp' initialized here}}
Modified: cfe/trunk/test/Analysis/uninit-const.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/uninit-const.cpp?rev=368773&r1=368772&r2=368773&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/uninit-const.cpp (original)
+++ cfe/trunk/test/Analysis/uninit-const.cpp Tue Aug 13 16:48:10 2019
@@ -66,8 +66,8 @@ void f6_1(void) {
void f6_2(void) {
int t; //expected-note {{'t' declared without an initial value}}
- int &p = t;
- int &s = p;
+ int &p = t; //expected-note {{'p' initialized here}}
+ int &s = p; //expected-note {{'s' initialized here}}
int &q = s; //expected-note {{'q' initialized here}}
doStuff6(q); //expected-warning {{1st function call argument is an uninitialized value}}
//expected-note at -1 {{1st function call argument is an uninitialized value}}
@@ -96,7 +96,7 @@ void f6(void) {
void f5(void) {
- int t;
+ int t; // expected-note {{'t' declared without an initial value}}
int* tp = &t; // expected-note {{'tp' initialized here}}
doStuff_uninit(tp); // expected-warning {{1st function call argument is a pointer to uninitialized value}}
// expected-note at -1 {{1st function call argument is a pointer to uninitialized value}}
More information about the cfe-commits
mailing list