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 &Dst) { ExplodedNodeSet dstPreStmt; getCheckerManager().runCheckersForPreStmt(dstPreStmt, Pred, CastE, *this); if (CastE->getCastKind() == CK_LValueToRValue || CastE->getCastKind() == CK_LValueToRValueBitCast) { for (ExplodedNode *subExprNode : dstPreStmt) { ProgramStateRef state = subExprNode->getState(); const LocationContext *LCtx = subExprNode->getLocationContext(); evalLoad(Dst, CastE, CastE, subExprNode, state, state->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 <col:17, col:45> 'void *' <LValueToRValueBitCast> ``` 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