Skip to content

Commit 971e696

Browse files
authored
[AST] Fix UB appearing due to strict aliasing rule violation (#85286)
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` (due to strict aliasing rule), which leads to `nameLoc.isValid()` being mistakenly computed as `true`. This patch resolves the issue by handling this special case separately.
1 parent ba47e23 commit 971e696

File tree

1 file changed

+8
-2
lines changed

1 file changed

+8
-2
lines changed

include/swift/AST/DeclNameLoc.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,11 @@ class DeclNameLoc {
6060
/// Retrieve a pointer to either the only source location that was
6161
/// stored or to the array of source locations that was stored.
6262
SourceLoc const * getSourceLocs() const {
63-
if (NumArgumentLabels == 0 && !HasModuleSelectorLoc)
63+
if (NumArgumentLabels == 0 && !HasModuleSelectorLoc) {
64+
if (LocationInfo == nullptr)
65+
return nullptr;
6466
return reinterpret_cast<SourceLoc const *>(&LocationInfo);
67+
}
6568

6669
return reinterpret_cast<SourceLoc const *>(LocationInfo);
6770
}
@@ -110,7 +113,10 @@ class DeclNameLoc {
110113

111114
/// Retrieve the location of the base name.
112115
SourceLoc getBaseNameLoc() const {
113-
return getSourceLocs()[BaseNameIndex];
116+
const SourceLoc *SourceLocs = getSourceLocs();
117+
if (SourceLocs == nullptr)
118+
return SourceLoc();
119+
return SourceLocs[BaseNameIndex];
114120
}
115121

116122
/// Retrieve the location of the left parentheses.

0 commit comments

Comments
 (0)