aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Analysis/ThreadSafety.cpp
diff options
context:
space:
mode:
authorMarco Elver <elver@google.com>2025-09-23 09:57:35 +0200
committerGitHub <noreply@github.com>2025-09-23 09:57:35 +0200
commit08de00ad22e71d74bcfdecd61502d0caea7eefb0 (patch)
treebd5a20ecda5e8a4b56bda77edd41688c59250ba0 /clang/lib/Analysis/ThreadSafety.cpp
parent242a1e2fb1b2ddefc8dcde73e22ce3f06f6a8188 (diff)
downloadllvm-08de00ad22e71d74bcfdecd61502d0caea7eefb0.zip
llvm-08de00ad22e71d74bcfdecd61502d0caea7eefb0.tar.gz
llvm-08de00ad22e71d74bcfdecd61502d0caea7eefb0.tar.bz2
Thread Safety Analysis: Fix recursive capability alias resolution (#159921)
Fix a false positive in thread safety alias analysis caused by incorrect late resolution of aliases. The analysis previously failed to distinguish between an alias and its defining expression; reassigning a variable within that expression (e.g., `ptr` in `alias = ptr->field`) would incorrectly change the dependent alias as well. The fix is to properly use LocalVariableMap::lookupExpr's updated context in a recursive lookup. Reported-by: Christoph Hellwig <hch@lst.de> Link: https://lkml.kernel.org/r/20250919140803.GA23745@lst.de
Diffstat (limited to 'clang/lib/Analysis/ThreadSafety.cpp')
-rw-r--r--clang/lib/Analysis/ThreadSafety.cpp45
1 files changed, 24 insertions, 21 deletions
diff --git a/clang/lib/Analysis/ThreadSafety.cpp b/clang/lib/Analysis/ThreadSafety.cpp
index cee98d5..d19f86a 100644
--- a/clang/lib/Analysis/ThreadSafety.cpp
+++ b/clang/lib/Analysis/ThreadSafety.cpp
@@ -1668,13 +1668,13 @@ void ThreadSafetyAnalyzer::getEdgeLockset(FactSet& Result,
const CFGBlockInfo *PredBlockInfo = &BlockInfo[PredBlock->getBlockID()];
const LocalVarContext &LVarCtx = PredBlockInfo->ExitContext;
- // Temporarily set the lookup context for SExprBuilder.
- SxBuilder.setLookupLocalVarExpr([&](const NamedDecl *D) -> const Expr * {
- if (!Handler.issueBetaWarnings())
- return nullptr;
- auto Ctx = LVarCtx;
- return LocalVarMap.lookupExpr(D, Ctx);
- });
+ if (Handler.issueBetaWarnings()) {
+ // Temporarily set the lookup context for SExprBuilder.
+ SxBuilder.setLookupLocalVarExpr(
+ [this, Ctx = LVarCtx](const NamedDecl *D) mutable -> const Expr * {
+ return LocalVarMap.lookupExpr(D, Ctx);
+ });
+ }
auto Cleanup = llvm::make_scope_exit(
[this] { SxBuilder.setLookupLocalVarExpr(nullptr); });
@@ -1722,6 +1722,19 @@ class BuildLockset : public ConstStmtVisitor<BuildLockset> {
LocalVariableMap::Context LVarCtx;
unsigned CtxIndex;
+ // To update and adjust the context.
+ void updateLocalVarMapCtx(const Stmt *S) {
+ if (S)
+ LVarCtx = Analyzer->LocalVarMap.getNextContext(CtxIndex, S, LVarCtx);
+ if (!Analyzer->Handler.issueBetaWarnings())
+ return;
+ // The lookup closure needs to be reconstructed with the refreshed LVarCtx.
+ Analyzer->SxBuilder.setLookupLocalVarExpr(
+ [this, Ctx = LVarCtx](const NamedDecl *D) mutable -> const Expr * {
+ return Analyzer->LocalVarMap.lookupExpr(D, Ctx);
+ });
+ }
+
// helper functions
void checkAccess(const Expr *Exp, AccessKind AK,
@@ -1747,13 +1760,7 @@ public:
: ConstStmtVisitor<BuildLockset>(), Analyzer(Anlzr), FSet(Info.EntrySet),
FunctionExitFSet(FunctionExitFSet), LVarCtx(Info.EntryContext),
CtxIndex(Info.EntryIndex) {
- Analyzer->SxBuilder.setLookupLocalVarExpr(
- [this](const NamedDecl *D) -> const Expr * {
- if (!Analyzer->Handler.issueBetaWarnings())
- return nullptr;
- auto Ctx = LVarCtx;
- return Analyzer->LocalVarMap.lookupExpr(D, Ctx);
- });
+ updateLocalVarMapCtx(nullptr);
}
~BuildLockset() { Analyzer->SxBuilder.setLookupLocalVarExpr(nullptr); }
@@ -2259,9 +2266,7 @@ void BuildLockset::VisitBinaryOperator(const BinaryOperator *BO) {
if (!BO->isAssignmentOp())
return;
- // adjust the context
- LVarCtx = Analyzer->LocalVarMap.getNextContext(CtxIndex, BO, LVarCtx);
-
+ updateLocalVarMapCtx(BO);
checkAccess(BO->getLHS(), AK_Written);
}
@@ -2307,8 +2312,7 @@ void BuildLockset::examineArguments(const FunctionDecl *FD,
}
void BuildLockset::VisitCallExpr(const CallExpr *Exp) {
- // adjust the context
- LVarCtx = Analyzer->LocalVarMap.getNextContext(CtxIndex, Exp, LVarCtx);
+ updateLocalVarMapCtx(Exp);
if (const auto *CE = dyn_cast<CXXMemberCallExpr>(Exp)) {
const auto *ME = dyn_cast<MemberExpr>(CE->getCallee());
@@ -2404,8 +2408,7 @@ static const Expr *UnpackConstruction(const Expr *E) {
}
void BuildLockset::VisitDeclStmt(const DeclStmt *S) {
- // adjust the context
- LVarCtx = Analyzer->LocalVarMap.getNextContext(CtxIndex, S, LVarCtx);
+ updateLocalVarMapCtx(S);
for (auto *D : S->getDeclGroup()) {
if (auto *VD = dyn_cast_or_null<VarDecl>(D)) {