From 1de628932262d2d437c7ed281cdff6e286d88c01 Mon Sep 17 00:00:00 2001 From: Daniil Kovalev Date: Mon, 3 Nov 2025 19:07:42 +0300 Subject: [PATCH] [AST] Fix UB appearing due to strict aliasing rule violation This fixes the following tests which are now crashing due to hitting unreachable "no buffer containing location found" in `SourceManager::findBufferContainingLoc`: - attr/attr_dynamic_member_lookup.swift - AutoDiff/Sema/DerivativeRegistrationCrossModule/main.swift - Constraints/construction.swift - Constraints/members.swift - NameLookup/accessibility.swift - Sema/call_as_function_simple.swift The root cause of the crash is as follows. All the tests involve emitting `InaccessibleMemberFailure` error diagnostic (see `InaccessibleMemberFailure::diagnoseAsError`). When `DeclNameLoc nameLoc` is initialized via default constructor and is not re-assigned with smth meaningful later, the check `nameLoc.isValid()` returns `true` even though it should be `false`. It turns out that we treat `const void *LocationInfo` as `SourceLoc` and hope that if `LocationInfo` is `nullptr`, casting this to `SourceLoc` would produce a "default" `SourceLoc` with `Pointer` member set to `nullptr`. But such a cast (see `getSourceLocs()` member of `DeclNameLoc`) is undefined behavior. So, the compiler assumes that `Pointer` member of `SourceLoc` we try to cast to is not `nullptr`, which leads to `nameLoc.isValid()` being mistakenly computed as `true`. This patch resolves the issue by handling this special case separately. --- include/swift/AST/DeclNameLoc.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/include/swift/AST/DeclNameLoc.h b/include/swift/AST/DeclNameLoc.h index 85dbb946c3108..077d2ccb651df 100644 --- a/include/swift/AST/DeclNameLoc.h +++ b/include/swift/AST/DeclNameLoc.h @@ -60,8 +60,11 @@ class DeclNameLoc { /// Retrieve a pointer to either the only source location that was /// stored or to the array of source locations that was stored. SourceLoc const * getSourceLocs() const { - if (NumArgumentLabels == 0 && !HasModuleSelectorLoc) + if (NumArgumentLabels == 0 && !HasModuleSelectorLoc) { + if (LocationInfo == nullptr) + return nullptr; return reinterpret_cast(&LocationInfo); + } return reinterpret_cast(LocationInfo); } @@ -110,7 +113,10 @@ class DeclNameLoc { /// Retrieve the location of the base name. SourceLoc getBaseNameLoc() const { - return getSourceLocs()[BaseNameIndex]; + const SourceLoc *SourceLocs = getSourceLocs(); + if (SourceLocs == nullptr) + return SourceLoc(); + return SourceLocs[BaseNameIndex]; } /// Retrieve the location of the left parentheses.