mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[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.
This commit is contained in:
@@ -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<SourceLoc const *>(&LocationInfo);
|
||||
}
|
||||
|
||||
return reinterpret_cast<SourceLoc const *>(LocationInfo);
|
||||
}
|
||||
@@ -110,7 +113,10 @@ public:
|
||||
|
||||
/// 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.
|
||||
|
||||
Reference in New Issue
Block a user