Skip to content

Commit e4fb140

Browse files
authored
Merge pull request swiftlang#20501 from davezarzycki/fix_28870_crasher
[AST] NFC: Add reentrancy check to associated type anchor walk
2 parents 637230d + e8eabd7 commit e4fb140

File tree

1 file changed

+20
-7
lines changed

1 file changed

+20
-7
lines changed

lib/AST/Decl.cpp

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3245,24 +3245,37 @@ AssociatedTypeDecl::getOverriddenDecls() const {
32453245
return assocTypes;
32463246
}
32473247

3248-
AssociatedTypeDecl *AssociatedTypeDecl::getAssociatedTypeAnchor() const {
3249-
auto overridden = getOverriddenDecls();
3248+
namespace {
3249+
static AssociatedTypeDecl *getAssociatedTypeAnchor(
3250+
const AssociatedTypeDecl *ATD,
3251+
llvm::SmallSet<const AssociatedTypeDecl *, 8> &searched) {
3252+
auto overridden = ATD->getOverriddenDecls();
32503253

32513254
// If this declaration does not override any other declarations, it's
32523255
// the anchor.
3253-
if (overridden.empty()) return const_cast<AssociatedTypeDecl *>(this);
3256+
if (overridden.empty()) return const_cast<AssociatedTypeDecl *>(ATD);
32543257

3255-
// Find the best anchor among the anchors of the overridden decls.
3258+
// Find the best anchor among the anchors of the overridden decls and avoid
3259+
// reentrancy when erroneous cyclic protocols exist.
32563260
AssociatedTypeDecl *bestAnchor = nullptr;
32573261
for (auto assocType : overridden) {
3258-
assert(this != assocType && "AssociatedTypeDecl cannot override itself");
3259-
auto anchor = assocType->getAssociatedTypeAnchor();
3260-
if (!bestAnchor || compare(anchor, bestAnchor) < 0)
3262+
if (!searched.insert(assocType).second)
3263+
continue;
3264+
auto anchor = getAssociatedTypeAnchor(assocType, searched);
3265+
if (!anchor)
3266+
continue;
3267+
if (!bestAnchor || AbstractTypeParamDecl::compare(anchor, bestAnchor) < 0)
32613268
bestAnchor = anchor;
32623269
}
32633270

32643271
return bestAnchor;
32653272
}
3273+
};
3274+
3275+
AssociatedTypeDecl *AssociatedTypeDecl::getAssociatedTypeAnchor() const {
3276+
llvm::SmallSet<const AssociatedTypeDecl *, 8> searched;
3277+
return ::getAssociatedTypeAnchor(this, searched);
3278+
}
32663279

32673280
EnumDecl::EnumDecl(SourceLoc EnumLoc,
32683281
Identifier Name, SourceLoc NameLoc,

0 commit comments

Comments
 (0)