llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang-tools-extra Author: Vasiliy Kulikov (segoon) <details> <summary>Changes</summary> --- Full diff: https://github.com/llvm/llvm-project/pull/145307.diff 8 Files Affected: - (modified) clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp (+3) - (modified) clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt (+1) - (added) clang-tools-extra/clang-tidy/bugprone/TaxiAsyncUseAfterFreeCheck.cpp (+58) - (added) clang-tools-extra/clang-tidy/bugprone/TaxiAsyncUseAfterFreeCheck.h (+33) - (modified) clang-tools-extra/docs/ReleaseNotes.rst (+5) - (added) clang-tools-extra/docs/clang-tidy/checks/bugprone/taxi-async-use-after-free.rst (+6) - (modified) clang-tools-extra/docs/clang-tidy/checks/list.rst (+1) - (added) clang-tools-extra/test/clang-tidy/checkers/bugprone/taxi-async-use-after-free.cpp (+53) ``````````diff diff --git a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp index b780a85bdf3fe..e22741e66580f 100644 --- a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp @@ -83,6 +83,7 @@ #include "SwappedArgumentsCheck.h" #include "SwitchMissingDefaultCaseCheck.h" #include "TaggedUnionMemberCountCheck.h" +#include "TaxiAsyncUseAfterFreeCheck.h" #include "TerminatingContinueCheck.h" #include "ThrowKeywordMissingCheck.h" #include "TooSmallLoopVariableCheck.h" @@ -151,6 +152,8 @@ class BugproneModule : public ClangTidyModule { "bugprone-incorrect-enable-if"); CheckFactories.registerCheck<IncorrectEnableSharedFromThisCheck>( "bugprone-incorrect-enable-shared-from-this"); + CheckFactories.registerCheck<TaxiAsyncUseAfterFreeCheck>( + "bugprone-taxi-async-use-after-free"); CheckFactories.registerCheck<UnintendedCharOstreamOutputCheck>( "bugprone-unintended-char-ostream-output"); CheckFactories.registerCheck<ReturnConstRefFromParameterCheck>( diff --git a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt index e310ea9c94543..b39177320b6ce 100644 --- a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt @@ -30,6 +30,7 @@ add_clang_library(clangTidyBugproneModule STATIC InaccurateEraseCheck.cpp IncorrectEnableIfCheck.cpp IncorrectEnableSharedFromThisCheck.cpp + TaxiAsyncUseAfterFreeCheck.cpp UnintendedCharOstreamOutputCheck.cpp ReturnConstRefFromParameterCheck.cpp SuspiciousStringviewDataUsageCheck.cpp diff --git a/clang-tools-extra/clang-tidy/bugprone/TaxiAsyncUseAfterFreeCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/TaxiAsyncUseAfterFreeCheck.cpp new file mode 100644 index 0000000000000..c044cf7b56f72 --- /dev/null +++ b/clang-tools-extra/clang-tidy/bugprone/TaxiAsyncUseAfterFreeCheck.cpp @@ -0,0 +1,58 @@ +//===--- TaxiAsyncUseAfterFreeCheck.cpp - clang-tidy ----------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "TaxiAsyncUseAfterFreeCheck.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" + +using namespace clang::ast_matchers; + +namespace clang::tidy::bugprone { + +void TaxiAsyncUseAfterFreeCheck::registerMatchers(MatchFinder* Finder) { + auto hasAsyncName = hasAnyName( + "Async", "AsyncNoSpan", "SharedAsyncNoSpan", "CriticalAsyncNoSpan", + "SharedCriticalAsyncNoSpan", "CriticalAsync", "SharedCriticalAsync"); + + Finder->addMatcher( + lambdaExpr( + hasParent(materializeTemporaryExpr(hasParent(callExpr( + hasParent(cxxMemberCallExpr( + + callee(cxxMethodDecl(hasName("push_back"))), + + on(declRefExpr(hasDeclaration(varDecl().bind("tasks")))))), + + callee(functionDecl(hasAsyncName))))))) + .bind("lambda"), + this); +} + +void TaxiAsyncUseAfterFreeCheck::check(const MatchFinder::MatchResult& Result) { + const auto* MatchedLambda = Result.Nodes.getNodeAs<LambdaExpr>("lambda"); + const auto* MatchedTasks = Result.Nodes.getNodeAs<VarDecl>("tasks"); + const SourceLocation TasksLocation = MatchedTasks->getLocation(); + + for (const auto& Capture : MatchedLambda->captures()) { + if (!Capture.capturesVariable() || Capture.getCaptureKind() != LCK_ByRef) + continue; + + const ValueDecl* CapturedVarDecl = Capture.getCapturedVar(); + if (CapturedVarDecl->getType().getCanonicalType()->isLValueReferenceType() || + CapturedVarDecl->getType().getCanonicalType()->isRValueReferenceType()) { + continue; + } + + if (CapturedVarDecl->getLocation() >= TasksLocation) { + diag(Capture.getLocation(), "captured here"); + diag(CapturedVarDecl->getLocation(), "variable can be used after free"); + diag(TasksLocation, "std::vector<Task> can die after variable"); + } + } +} + +} // namespace clang::tidy::bugprone diff --git a/clang-tools-extra/clang-tidy/bugprone/TaxiAsyncUseAfterFreeCheck.h b/clang-tools-extra/clang-tidy/bugprone/TaxiAsyncUseAfterFreeCheck.h new file mode 100644 index 0000000000000..7e56e6a2b3c23 --- /dev/null +++ b/clang-tools-extra/clang-tidy/bugprone/TaxiAsyncUseAfterFreeCheck.h @@ -0,0 +1,33 @@ +//===--- TaxiAsyncUseAfterFreeCheck.h - clang-tidy --------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_TAXIASYNCUSEAFTERFREECHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_TAXIASYNCUSEAFTERFREECHECK_H + +#include "../ClangTidyCheck.h" + +namespace clang::tidy::bugprone { + +/// Use-after-free for engine::Async. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone/taxi-async-use-after-free.html +class TaxiAsyncUseAfterFreeCheck : public ClangTidyCheck { +public: + TaxiAsyncUseAfterFreeCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; + bool isLanguageVersionSupported(const LangOptions &LangOpts) const override { + return LangOpts.CPlusPlus; + } +}; + +} // namespace clang::tidy::bugprone + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_TAXIASYNCUSEAFTERFREECHECK_H diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 579fca54924d5..ea1081e603b72 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -124,6 +124,11 @@ New checks pointer and store it as class members without handle the copy and move constructors and the assignments. +- New :doc:`bugprone-taxi-async-use-after-free + <clang-tidy/checks/bugprone/taxi-async-use-after-free>` check. + + Use-after-free for engine::Async. + - New :doc:`bugprone-unintended-char-ostream-output <clang-tidy/checks/bugprone/unintended-char-ostream-output>` check. diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/taxi-async-use-after-free.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/taxi-async-use-after-free.rst new file mode 100644 index 0000000000000..bff4f8dd974b3 --- /dev/null +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/taxi-async-use-after-free.rst @@ -0,0 +1,6 @@ +.. title:: clang-tidy - bugprone-taxi-async-use-after-free + +bugprone-taxi-async-use-after-free +================================== + +FIXME: Describe what patterns does the check detect and why. Give examples. diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst index 18f1467285fab..c098ee3d5efa6 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/list.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst @@ -151,6 +151,7 @@ Clang-Tidy Checks :doc:`bugprone-swapped-arguments <bugprone/swapped-arguments>`, "Yes" :doc:`bugprone-switch-missing-default-case <bugprone/switch-missing-default-case>`, :doc:`bugprone-tagged-union-member-count <bugprone/tagged-union-member-count>`, + :doc:`bugprone-taxi-async-use-after-free <bugprone/taxi-async-use-after-free>`, "Yes" :doc:`bugprone-terminating-continue <bugprone/terminating-continue>`, "Yes" :doc:`bugprone-throw-keyword-missing <bugprone/throw-keyword-missing>`, :doc:`bugprone-too-small-loop-variable <bugprone/too-small-loop-variable>`, diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/taxi-async-use-after-free.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/taxi-async-use-after-free.cpp new file mode 100644 index 0000000000000..f8d4eee0411cb --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/taxi-async-use-after-free.cpp @@ -0,0 +1,53 @@ +// RUN: %check_clang_tidy %s bugprone-taxi-async-use-after-free %t + +namespace std { + +template<typename T> +class vector { +public: + void push_back(T) {} +}; + +} + +namespace engine { + +template <typename Function, typename... Args> +int Async(Function&& f, Args&&... args) { + return 1; +} + +} + +void f_ok() { + int x = 1; + std::vector<int> v; + + v.push_back(engine::Async([&x]{ x = 2;})); +} + +void f_use_after_free() { + std::vector<int> v; + // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: std::vector<Task> can die after variable [bugprone-taxi-async-use-after-free] + int x = 1; + // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: variable can be used after free [bugprone-taxi-async-use-after-free] + + v.push_back(engine::Async([&x]{ x = 2;})); + // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: captured here [bugprone-taxi-async-use-after-free] +} + +void f_ref() { + int xx = 1; + std::vector<int> v; + int &x = x; + + v.push_back(engine::Async([&x]{ x = 2;})); +} + +void f_ref_ref() { + int xx = 1; + std::vector<int> v; + int &&x = static_cast<int&&>(xx); + + v.push_back(engine::Async([&x]{ x = 2;})); +} `````````` </details> https://github.com/llvm/llvm-project/pull/145307 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits