diff options
author | Marco Elver <elver@google.com> | 2025-09-23 09:57:35 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-09-23 09:57:35 +0200 |
commit | 08de00ad22e71d74bcfdecd61502d0caea7eefb0 (patch) | |
tree | bd5a20ecda5e8a4b56bda77edd41688c59250ba0 /clang/lib/Analysis/ThreadSafety.cpp | |
parent | 242a1e2fb1b2ddefc8dcde73e22ce3f06f6a8188 (diff) | |
download | llvm-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.cpp | 45 |
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)) { |