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