llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang-static-analyzer-1

Author: Ziqing Luo (ziqingluo-90)

<details>
<summary>Changes</summary>

I am investigating a CSA crash: https://godbolt.org/z/fEExYqoWM.  If one 
changes the `__builtin_bit_cast` to a C-style cast, the test will be fine.  So 
the problem is specific to `__builtin_bit_cast`.

Looking at the piece of code below, it seems that CSA handles 
`__builtin_bit_cast` just as an `LValueToRValue` cast.  The actual operation of 
cast-to-target-type is missing. 
```
void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
                           ExplodedNode *Pred, ExplodedNodeSet &amp;Dst) {

  ExplodedNodeSet dstPreStmt;
  getCheckerManager().runCheckersForPreStmt(dstPreStmt, Pred, CastE, *this);

  if (CastE-&gt;getCastKind() == CK_LValueToRValue ||
      CastE-&gt;getCastKind() == CK_LValueToRValueBitCast) {
    for (ExplodedNode *subExprNode : dstPreStmt) {
      ProgramStateRef state = subExprNode-&gt;getState();
      const LocationContext *LCtx = subExprNode-&gt;getLocationContext();
      evalLoad(Dst, CastE, CastE, subExprNode, state, state-&gt;getSVal(Ex, 
LCtx));
    }
    return;
  }
```

The `BuiltinBitCastExpr` node always have the kind `LValueToRValueBitCast`.  I 
suppose it is just associated to the second argument of a `__builtin_bit_cast` 
call.  
```
-BuiltinBitCastExpr &lt;col:17, col:45&gt; 'void *' 
&lt;LValueToRValueBitCast&gt;
```

I'm trying to add the missing part.

---
Full diff: https://github.com/llvm/llvm-project/pull/139188.diff


3 Files Affected:

- (modified) clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp (+25-1) 
- (modified) clang/test/Analysis/builtin_bitcast.cpp (+12-2) 
- (modified) clang/test/Analysis/exercise-ps.c (+1-1) 


``````````diff
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp 
b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
index 3d0a69a515ab8..f2f640f459776 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
@@ -287,10 +287,34 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const 
Expr *Ex,
 
   if (CastE->getCastKind() == CK_LValueToRValue ||
       CastE->getCastKind() == CK_LValueToRValueBitCast) {
+    ExplodedNodeSet dstEvalLoad;
+
     for (ExplodedNode *subExprNode : dstPreStmt) {
       ProgramStateRef state = subExprNode->getState();
       const LocationContext *LCtx = subExprNode->getLocationContext();
-      evalLoad(Dst, CastE, CastE, subExprNode, state, state->getSVal(Ex, 
LCtx));
+      evalLoad(dstEvalLoad, CastE, CastE, subExprNode, state,
+               state->getSVal(Ex, LCtx));
+    }
+    if (CastE->getCastKind() == CK_LValueToRValue) {
+      Dst.insert(dstEvalLoad);
+      return;
+    }
+    assert(CastE->getCastKind() == CK_LValueToRValueBitCast &&
+           "unexpected cast kind");
+    // Need to simulate the actual cast operation:
+    StmtNodeBuilder Bldr(dstEvalLoad, Dst, *currBldrCtx);
+
+    for (ExplodedNode *Node : dstEvalLoad) {
+      ProgramStateRef state = Node->getState();
+      const LocationContext *LCtx = Node->getLocationContext();
+      // getAsRegion should always be successful since Ex is an lvalue:
+      SVal OrigV = state->getSVal(state->getSVal(Ex, LCtx).getAsRegion());
+      SVal CastedV =
+          svalBuilder.evalCast(svalBuilder.simplifySVal(state, OrigV),
+                               CastE->getType(), Ex->getType());
+
+      state = state->BindExpr(CastE, LCtx, CastedV);
+      Bldr.generateNode(CastE, Node, state);
     }
     return;
   }
diff --git a/clang/test/Analysis/builtin_bitcast.cpp 
b/clang/test/Analysis/builtin_bitcast.cpp
index 5a0d9e7189b8e..9309ca7785a92 100644
--- a/clang/test/Analysis/builtin_bitcast.cpp
+++ b/clang/test/Analysis/builtin_bitcast.cpp
@@ -39,7 +39,7 @@ struct A {
   }
 };
 void gh_69922(size_t p) {
-  // expected-warning-re@+1 {{(reg_${{[0-9]+}}<size_t p>) & 1U}}
+  // expected-warning@+1 {{Unknown}}
   clang_analyzer_dump(__builtin_bit_cast(A*, p & 1));
 
   __builtin_bit_cast(A*, p & 1)->set(2); // no-crash
@@ -49,5 +49,15 @@ void gh_69922(size_t p) {
   // store to the member variable `n`.
 
   clang_analyzer_dump(__builtin_bit_cast(A*, p & 1)->n); // Ideally, this 
should print "2".
-  // expected-warning-re@-1 {{(reg_${{[0-9]+}}<size_t p>) & 1U}}
+  // expected-warning@-1 {{Unknown}}
+}
+
+namespace {
+  typedef unsigned long uintptr_t;
+  
+  bool previously_crash(const void *& ptr) {
+    clang_analyzer_dump(__builtin_bit_cast(void*, static_cast<uintptr_t>(-1)));
+    // expected-warning-re@-1 {{{{[0-9]+}} (Loc)}}
+    return ptr == __builtin_bit_cast(void*, static_cast<uintptr_t>(-1));
+  }
 }
diff --git a/clang/test/Analysis/exercise-ps.c 
b/clang/test/Analysis/exercise-ps.c
index 50643d5b04687..21d97a364e190 100644
--- a/clang/test/Analysis/exercise-ps.c
+++ b/clang/test/Analysis/exercise-ps.c
@@ -41,7 +41,7 @@ void f4(char *array) {
 
   _Static_assert(sizeof(int) == 4, "Wrong triple for the test");
 
-  clang_analyzer_dump_int(__builtin_bit_cast(int, b)); // expected-warning 
{{lazyCompoundVal}}
+  clang_analyzer_dump_int(__builtin_bit_cast(int, b)); // expected-warning 
{{Unknown}}
   clang_analyzer_dump_int(array[__builtin_bit_cast(int, b)]); // 
expected-warning {{Unknown}}
 
   array[__builtin_bit_cast(int, b)] = 0x10; // no crash

``````````

</details>


https://github.com/llvm/llvm-project/pull/139188
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to