[clang] [clang] Fix possible nullptr deref in BuildCXXNestedNameSpecifier (PR #166995)
Paul Kirth via cfe-commits
cfe-commits at lists.llvm.org
Fri Nov 7 10:57:56 PST 2025
https://github.com/ilovepi created https://github.com/llvm/llvm-project/pull/166995
There is a possible nullptr deref in BuildCXXNestedNameSpecifier when calling ExtendNestedNameSpecifier or using isa<>. This initially showed up as a crash in clangd, that didn't manifest in when compiling w/ clang. The reduced test case added in this patch, however does expose the issue in clang. Testing locally shows that both this test case and the original clangd issue are fixed by checking the validity of the pointer before trying to dispatch. Since all code paths require the pointer to be valid (usually by virtue of a dyn_cast or isa<> check), there should be no functional difference.
Fixes #166843
>From dbedc1cb2ccd8e6b94b4d8f575722551af00705a Mon Sep 17 00:00:00 2001
From: Paul Kirth <paulkirth at google.com>
Date: Fri, 7 Nov 2025 10:51:39 -0800
Subject: [PATCH] [clang] Fix possible nullptr deref in
BuildCXXNestedNameSpecifier
There is a possible nullptr deref in BuildCXXNestedNameSpecifier when
calling ExtendNestedNameSpecifier or using isa<>. This initially showed
up as a crash in clangd, that didn't manifest in when compiling w/
clang. The reduced test case added in this patch, however does expose
the issue in clang. Testing locally shows that both this test case and
the original clangd issue are fixed by checking the validity of the
pointer before trying to dispatch. Since all code paths require the
pointer to be valid (usually by virtue of a dyn_cast or isa<> check),
there should be no functional difference.
Fixes #166843
---
clang/lib/Sema/SemaCXXScopeSpec.cpp | 39 +++++++++++++++--------------
1 file changed, 20 insertions(+), 19 deletions(-)
diff --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp b/clang/lib/Sema/SemaCXXScopeSpec.cpp
index c52fc5bf815af..29e697d9eb029 100644
--- a/clang/lib/Sema/SemaCXXScopeSpec.cpp
+++ b/clang/lib/Sema/SemaCXXScopeSpec.cpp
@@ -779,25 +779,26 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo,
}
if (!Found.empty()) {
- const auto *ND = Found.getAsSingle<NamedDecl>();
- if (::ExtendNestedNameSpecifier(*this, SS, ND, IdInfo.IdentifierLoc,
- IdInfo.CCLoc)) {
- const Type *T = SS.getScopeRep().getAsType();
- Diag(IdInfo.IdentifierLoc, diag::err_expected_class_or_namespace)
- << QualType(T, 0) << getLangOpts().CPlusPlus;
- // Recover with this type if it would be a valid nested name specifier.
- return !T->getAsCanonical<TagType>();
- }
- if (isa<TemplateDecl>(ND)) {
- ParsedType SuggestedType;
- DiagnoseUnknownTypeName(IdInfo.Identifier, IdInfo.IdentifierLoc, S, &SS,
- SuggestedType);
- } else {
- Diag(IdInfo.IdentifierLoc, diag::err_expected_class_or_namespace)
- << IdInfo.Identifier << getLangOpts().CPlusPlus;
- if (NamedDecl *ND = Found.getAsSingle<NamedDecl>())
- Diag(ND->getLocation(), diag::note_entity_declared_at)
- << IdInfo.Identifier;
+ if (const auto *ND = Found.getAsSingle<NamedDecl>()) {
+ if (::ExtendNestedNameSpecifier(*this, SS, ND, IdInfo.IdentifierLoc,
+ IdInfo.CCLoc)) {
+ const Type *T = SS.getScopeRep().getAsType();
+ Diag(IdInfo.IdentifierLoc, diag::err_expected_class_or_namespace)
+ << QualType(T, 0) << getLangOpts().CPlusPlus;
+ // Recover with this type if it would be a valid nested name specifier.
+ return !T->getAsCanonical<TagType>();
+ }
+ if (isa<TemplateDecl>(ND)) {
+ ParsedType SuggestedType;
+ DiagnoseUnknownTypeName(IdInfo.Identifier, IdInfo.IdentifierLoc, S, &SS,
+ SuggestedType);
+ } else {
+ Diag(IdInfo.IdentifierLoc, diag::err_expected_class_or_namespace)
+ << IdInfo.Identifier << getLangOpts().CPlusPlus;
+ if (NamedDecl *ND = Found.getAsSingle<NamedDecl>())
+ Diag(ND->getLocation(), diag::note_entity_declared_at)
+ << IdInfo.Identifier;
+ }
}
} else if (SS.isSet())
Diag(IdInfo.IdentifierLoc, diag::err_no_member) << IdInfo.Identifier
More information about the cfe-commits
mailing list