Skip to content

Commit bebde5d

Browse files
committed
Sema: avoid a use-after-free in ResolvedMemberResult
The use of the reference to a private implementation caused a silent use-after-free which would normally not trigger a problem as the use was pretty close by. The reference would copy the pointer and the destructor for the implementation would free the backing memory. We would then continue to use the free'd memory to query the information. The Windows heap allocator kindly scribbles over the memory which caused an invalid memory access, helping isolate the use-after-free.
1 parent 8975875 commit bebde5d

File tree

2 files changed

+20
-14
lines changed

2 files changed

+20
-14
lines changed

include/swift/Sema/IDETypeChecking.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,16 @@ namespace swift {
6565

6666
struct ResolvedMemberResult {
6767
struct Implementation;
68-
Implementation &Impl;
68+
Implementation *Impl;
6969

7070
ResolvedMemberResult();
7171
~ResolvedMemberResult();
72+
ResolvedMemberResult(const ResolvedMemberResult &) = delete;
73+
ResolvedMemberResult & operator=(ResolvedMemberResult &) = delete;
74+
ResolvedMemberResult(ResolvedMemberResult &&other) {
75+
Impl = other.Impl;
76+
other.Impl = nullptr;
77+
}
7278
operator bool() const;
7379
bool hasBestOverload() const;
7480
ValueDecl* getBestOverload() const;

lib/Sema/CSGen.cpp

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3773,28 +3773,28 @@ struct ResolvedMemberResult::Implementation {
37733773
Optional<unsigned> BestIdx;
37743774
};
37753775

3776-
ResolvedMemberResult::ResolvedMemberResult(): Impl(*new Implementation()) {};
3776+
ResolvedMemberResult::ResolvedMemberResult(): Impl(new Implementation()) {};
37773777

3778-
ResolvedMemberResult::~ResolvedMemberResult() { delete &Impl; };
3778+
ResolvedMemberResult::~ResolvedMemberResult() { delete Impl; };
37793779

37803780
ResolvedMemberResult::operator bool() const {
3781-
return !Impl.AllDecls.empty();
3781+
return !Impl->AllDecls.empty();
37823782
}
37833783

37843784
bool ResolvedMemberResult::
3785-
hasBestOverload() const { return Impl.BestIdx.hasValue(); }
3785+
hasBestOverload() const { return Impl->BestIdx.hasValue(); }
37863786

37873787
ValueDecl* ResolvedMemberResult::
3788-
getBestOverload() const { return Impl.AllDecls[Impl.BestIdx.getValue()]; }
3788+
getBestOverload() const { return Impl->AllDecls[Impl->BestIdx.getValue()]; }
37893789

37903790
ArrayRef<ValueDecl*> ResolvedMemberResult::
37913791
getMemberDecls(InterestedMemberKind Kind) {
3792-
auto Result = llvm::makeArrayRef(Impl.AllDecls);
3792+
auto Result = llvm::makeArrayRef(Impl->AllDecls);
37933793
switch (Kind) {
37943794
case InterestedMemberKind::Viable:
3795-
return Result.slice(Impl.ViableStartIdx);
3795+
return Result.slice(Impl->ViableStartIdx);
37963796
case InterestedMemberKind::Unviable:
3797-
return Result.slice(0, Impl.ViableStartIdx);
3797+
return Result.slice(0, Impl->ViableStartIdx);
37983798
case InterestedMemberKind::All:
37993799
return Result;
38003800
}
@@ -3816,10 +3816,10 @@ swift::resolveValueMember(DeclContext &DC, Type BaseTy, DeclName Name) {
38163816

38173817
// Keep track of all the unviable members.
38183818
for (auto Can : LookupResult.UnviableCandidates)
3819-
Result.Impl.AllDecls.push_back(Can.getDecl());
3819+
Result.Impl->AllDecls.push_back(Can.getDecl());
38203820

38213821
// Keep track of the start of viable choices.
3822-
Result.Impl.ViableStartIdx = Result.Impl.AllDecls.size();
3822+
Result.Impl->ViableStartIdx = Result.Impl->AllDecls.size();
38233823

38243824
// If no viable members, we are done.
38253825
if (LookupResult.ViableCandidates.empty())
@@ -3839,8 +3839,8 @@ swift::resolveValueMember(DeclContext &DC, Type BaseTy, DeclName Name) {
38393839

38403840
// If this VD is the best overload, keep track of its index.
38413841
if (VD == Selected)
3842-
Result.Impl.BestIdx = Result.Impl.AllDecls.size();
3843-
Result.Impl.AllDecls.push_back(VD);
3842+
Result.Impl->BestIdx = Result.Impl->AllDecls.size();
3843+
Result.Impl->AllDecls.push_back(VD);
38443844
}
38453845
return Result;
38463846
}
@@ -3898,4 +3898,4 @@ swift::getOriginalArgumentList(Expr *expr) {
38983898
}
38993899

39003900
return result;
3901-
}
3901+
}

0 commit comments

Comments
 (0)