Skip to content

[clang-tidy] fix nullptr dereference in bugprone-forwarding-reference #106856

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

5chmidti
Copy link
Contributor

@5chmidti 5chmidti commented Aug 31, 2024

Previously, when checking if a TemplateSpecializationType is either
enable_if or enable_if_t, the AST matcher would call
getTemplateName, getASTemplateDecl and getTemplatedDecl in
succession to check the NamedDecl returned from getTemplatedDecl is
an std::enable_if[_t]. In the linked issue, the pointer returned by
getTemplatedDecl is a nullptr that is unconditionally accessed,
resulting in a crash. Instead, the checking is done on the TemplateDecl
returned by getASTemplateDecl.

Fixes #106333

@llvmbot
Copy link
Member

llvmbot commented Aug 31, 2024

@llvm/pr-subscribers-clang-tidy

@llvm/pr-subscribers-clang-tools-extra

Author: Julian Schmidt (5chmidti)

Changes

Previously, when checking if a TemplateSpecializationType is either
enable_if or enable_if_t, the AST matcher would call
getTemplateName, getASTemplateDecl and getTemplatedDecl in
succession to check the NamedDecl returned from getTemplatedDecl is
std::enable_if[_t].
In the linked issue, the pointer returned by getTemplatedDecl is a
nullptr that is unconditionally accessed, resulting in a crash.
Instead, the checking is done on the TemplateDecl returned by
getASTemplateDecl.

Fixes #106333


Full diff: https://github.com/llvm/llvm-project/pull/106856.diff

3 Files Affected:

  • (modified) clang-tools-extra/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.cpp (+7-8)
  • (modified) clang-tools-extra/docs/ReleaseNotes.rst (+4)
  • (modified) clang-tools-extra/test/clang-tidy/checkers/bugprone/forwarding-reference-overload.cpp (+6)
diff --git a/clang-tools-extra/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.cpp
index c87b3ea7e26163..00e8f7e514368b 100644
--- a/clang-tools-extra/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.cpp
@@ -9,7 +9,6 @@
 #include "ForwardingReferenceOverloadCheck.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
-#include <algorithm>
 
 using namespace clang::ast_matchers;
 
@@ -19,14 +18,14 @@ namespace {
 // Check if the given type is related to std::enable_if.
 AST_MATCHER(QualType, isEnableIf) {
   auto CheckTemplate = [](const TemplateSpecializationType *Spec) {
-    if (!Spec || !Spec->getTemplateName().getAsTemplateDecl()) {
+    if (!Spec)
       return false;
-    }
-    const NamedDecl *TypeDecl =
-        Spec->getTemplateName().getAsTemplateDecl()->getTemplatedDecl();
-    return TypeDecl->isInStdNamespace() &&
-           (TypeDecl->getName() == "enable_if" ||
-            TypeDecl->getName() == "enable_if_t");
+
+    const TemplateDecl *TDecl = Spec->getTemplateName().getAsTemplateDecl();
+
+    return TDecl && TDecl->isInStdNamespace() &&
+           (TDecl->getName() == "enable_if" ||
+            TDecl->getName() == "enable_if_t");
   };
   const Type *BaseType = Node.getTypePtr();
   // Case: pointer or reference to enable_if.
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index b001a6ad446695..c2fdc7dc689fc1 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -104,6 +104,10 @@ New check aliases
 Changes in existing checks
 ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+- Improved :doc:`bugprone-forwarding-reference-overload
+  <clang-tidy/checks/bugprone/forwarding-reference-overload>` check by fixing
+  a crash when determining if an ``enable_if[_t]`` was found.
+
 - Improved :doc:`modernize-use-std-format
   <clang-tidy/checks/modernize/use-std-format>` check to support replacing
   member function calls too.
diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/forwarding-reference-overload.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/forwarding-reference-overload.cpp
index 92dfb718bb51b7..27315199c7ebae 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/forwarding-reference-overload.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/forwarding-reference-overload.cpp
@@ -261,3 +261,9 @@ class Test11 {
   Test11(const Test11 &) = default;
   Test11(Test11 &&) = default;
 };
+
+template <template <class> typename T, typename U>
+struct gh106333
+{
+    gh106333(U && arg1, T<int> arg2) {}
+};

Copy link
Contributor

@nicovank nicovank left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

Previously, when checking if a `TemplateSpecializationType` is either
`enable_if` or `enable_if_t`, the AST matcher would call
`getTemplateName`, `getASTemplateDecl` and `getTemplatedDecl` in
succession to check the `NamedDecl` returned from `getTemplatedDecl` is
`std::enable_if[_t]`.
In the linked issue, the poitner returned by `getTemplatedDecl` is a
`nullptr` that is unconditionally accessed, resulting in a crash.
Instead, the checking is done on the `TemplateDecl` returned by
`getASTemplateDecl`.

Fixes llvm#106333
@5chmidti 5chmidti force-pushed the clang_tidy_fix_bugprone_forwarding_reference_overload_crash branch from b0ab311 to f47b807 Compare September 16, 2024 21:22
@5chmidti 5chmidti merged commit 6357781 into llvm:main Sep 17, 2024
9 checks passed
tmsri pushed a commit to tmsri/llvm-project that referenced this pull request Sep 19, 2024
…llvm#106856)

Previously, when checking if a `TemplateSpecializationType` is either
`enable_if` or `enable_if_t`, the AST matcher would call
`getTemplateName`, `getASTemplateDecl` and `getTemplatedDecl` in
succession to check the `NamedDecl` returned from `getTemplatedDecl` is
an `std::enable_if[_t]`. In the linked issue, the pointer returned by 
`getTemplatedDecl` is a `nullptr` that is unconditionally accessed, 
resulting in a crash. Instead, the checking is done on the
`TemplateDecl`
returned by `getASTemplateDecl`.

Fixes llvm#106333
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

segfault in bugprone-forwarding-reference-overload check
4 participants