Skip to content

Commit 1329055

Browse files
committed
[Serialization] Fix deserializing opaque types for computed properties and subscripts
A client shouldn't know about the underlying type of an opaque type unless it can see the body of the naming decl. Attempting to read it can lead to accessing a hidden dependency and a compiler crash. This was protected by a check specific to function decls that left out var decls and subscripts. Fix this hole with a new service checking for inlinable attributes directly. rdar://117607906
1 parent 41dc466 commit 1329055

File tree

4 files changed

+42
-4
lines changed

4 files changed

+42
-4
lines changed

include/swift/AST/Decl.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3294,6 +3294,14 @@ class OpaqueTypeDecl final :
32943294
};
32953295
}
32963296

3297+
/// Should we consider the underlying type as visible to clients outside of
3298+
/// the module?
3299+
///
3300+
/// This is used during deserialization to determine if this information
3301+
/// can be read reliably. We should be careful to what data is accessed by
3302+
/// this service as \c this may not be fully consistent.
3303+
bool exportUnderylingTypeToClients() const;
3304+
32973305
/// The substitutions that map the generic parameters of the opaque type to
32983306
/// the unique underlying types, when that information is known.
32993307
llvm::Optional<SubstitutionMap> getUniqueUnderlyingTypeSubstitutions() const {

lib/AST/Decl.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9464,6 +9464,19 @@ GenericTypeParamDecl *OpaqueTypeDecl::getExplicitGenericParam(
94649464
return genericParamType->getDecl();
94659465
}
94669466

9467+
bool OpaqueTypeDecl::exportUnderylingTypeToClients() const {
9468+
auto mod = getDeclContext()->getParentModule();
9469+
if (mod->getResilienceStrategy() != ResilienceStrategy::Resilient)
9470+
return true;
9471+
9472+
ValueDecl *namingDecl = getNamingDecl();
9473+
if (namingDecl->getAttrs().hasAttribute<AlwaysEmitIntoClientAttr>() ||
9474+
namingDecl->getAttrs().hasAttribute<InlinableAttr>())
9475+
return true;
9476+
9477+
return false;
9478+
}
9479+
94679480
llvm::Optional<unsigned>
94689481
OpaqueTypeDecl::getAnonymousOpaqueParamOrdinal(TypeRepr *repr) const {
94699482
assert(NamingDeclAndHasOpaqueReturnTypeRepr.getInt() &&

lib/Serialization/Deserialization.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4244,14 +4244,17 @@ class DeclDeserializer {
42444244
else
42454245
opaqueDecl->setGenericSignature(GenericSignature());
42464246

4247-
auto *AFD = dyn_cast<AbstractFunctionDecl>(namingDecl);
4248-
if (MF.getResilienceStrategy() == ResilienceStrategy::Resilient &&
4249-
!MF.FileContext->getParentModule()->isMainModule() &&
4250-
AFD && AFD->getResilienceExpansion() != ResilienceExpansion::Minimal) {
4247+
if (!MF.FileContext->getParentModule()->isMainModule() &&
4248+
!opaqueDecl->exportUnderylingTypeToClients()) {
42514249
// Do not try to read the underlying type information if the function
42524250
// is not inlinable in clients. This reflects the swiftinterface behavior
42534251
// in where clients are only aware of the underlying type when the body
42544252
// of the function is public.
4253+
LLVM_DEBUG(
4254+
llvm::dbgs() << "Ignoring underlying information for opaque type of '";
4255+
llvm::dbgs() << namingDecl->getName();
4256+
llvm::dbgs() << "'\n";
4257+
);
42554258

42564259
} else if (underlyingTypeSubsID) {
42574260
auto subMapOrError = MF.getSubstitutionMapChecked(underlyingTypeSubsID);

test/Serialization/Safety/skip-reading-internal-details.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,10 @@
6868
// SAFE: Skipping unsafe deserialization: 'fileprivateFunc()'
6969
// SAFE: Skipping unsafe deserialization: 'refToIOI()'
7070

71+
// NEEDED: Ignoring underlying information for opaque type of 'opaqueReferencingPrivate()'
72+
// NEEDED: Ignoring underlying information for opaque type of 'opaqueReferencingPrivateVar'
73+
// NEEDED: Ignoring underlying information for opaque type of 'subscript(_:)'
74+
7175
//--- HiddenLib.swift
7276

7377
public struct HiddenStruct {
@@ -113,6 +117,14 @@ public extension V {
113117
}
114118

115119
private func referencedPrivateFunc(v: some V) -> some V { return v }
120+
121+
var opaqueReferencingPrivateVar: some V {
122+
referencedPrivateFunc(v: EV())
123+
}
124+
125+
subscript(v: some V) -> some V {
126+
referencedPrivateFunc(v: v)
127+
}
116128
}
117129

118130
//--- Client.swift
@@ -127,4 +139,6 @@ x.notAMember() // expected-error {{value of type 'PublicStruct' has no member 'n
127139
if #available(SwiftStdlib 5.1, *) {
128140
let v = EV()
129141
let _ = v.opaqueReferencingPrivate()
142+
let _ = v.opaqueReferencingPrivateVar
143+
let _ = v[v]
130144
}

0 commit comments

Comments
 (0)