-
Notifications
You must be signed in to change notification settings - Fork 13.5k
[analyzer] Fix crashing __builtin_bit_cast #139188
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Previously, CSA did not handle __builtin_bit_cast correctly. It evaluated the LvalueToRvalue conversion for the casting expression, but did not actually convert the value of the expression to be of the destination type. This commit fixes the problem. rdar://149987320
@llvm/pr-subscribers-clang @llvm/pr-subscribers-clang-static-analyzer-1 Author: Ziqing Luo (ziqingluo-90) ChangesI am investigating a CSA crash: https://godbolt.org/z/fEExYqoWM. If one changes the Looking at the piece of code below, it seems that CSA handles
The
I'm trying to add the missing part. Full diff: https://github.com/llvm/llvm-project/pull/139188.diff 3 Files Affected:
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
|
…rgument instead of evalLoad.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall LGTM, thanks for fixing this crash!
I dropped one (somewhat paranoid) inline question.
Moreover, I would suggest following the coding standard and use UpperCamelCase
for the variables that are freshly introduced (and perhaps also for the variables that were already existing, if you touch most references to them and could easily rename them). Unfortunately we cannot "jump to" this naming standard by globally renaming many variables (because that would heavily pollute the git history), but I think we should gradually transition by following the standard in new variables and perhaps renaming the variables in the code that we touch. (As a personal preference, I consistently update the variable names when I edit some code, but objectively it's also OK to keep the old names to preserve consistency with adjacent existing code.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM overall. Thank you!
I'm also in favor of following the LLVM coding style.
Thanks for reviewing! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
__builtin_bit_cast
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still LGTM.
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/11/builds/15055 Here is the relevant piece of the build log for the reference
|
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 anLValueToRValue
cast. The actual operation of cast-to-target-type is missing.The
BuiltinBitCastExpr
node always have the kindLValueToRValueBitCast
. I suppose it is just associated to the second argument of a__builtin_bit_cast
call.I'm trying to add the missing part.
Fixes #137417