Skip to content

Commit 2cd0d5e

Browse files
authored
Merge pull request #37768 from xymus/swiftmodule-sdk
[Serialization] Restrict loading swiftmodule files to the SDK that built them
2 parents c3e7626 + 51cec86 commit 2cd0d5e

File tree

22 files changed

+93
-12
lines changed

22 files changed

+93
-12
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -782,6 +782,9 @@ ERROR(serialization_name_mismatch_repl,none,
782782
ERROR(serialization_target_incompatible,Fatal,
783783
"module %0 was created for incompatible target %1: %2",
784784
(Identifier, StringRef, StringRef))
785+
ERROR(serialization_sdk_mismatch,Fatal,
786+
"cannot load module %0 built with SDK '%1' when using SDK '%2': %3",
787+
(Identifier, StringRef, StringRef, StringRef))
785788
ERROR(serialization_target_incompatible_repl,none,
786789
"module %0 was created for incompatible target %1: %2",
787790
(Identifier, StringRef, StringRef))

include/swift/AST/SearchPathOptions.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,10 @@ class SearchPathOptions {
8282
/// would for a non-system header.
8383
bool DisableModulesValidateSystemDependencies = false;
8484

85+
/// Enforce loading only serialized modules built with the same SDK
86+
/// as the context loading it.
87+
bool EnableSameSDKCheck = true;
88+
8589
/// A set of compiled modules that may be ready to use.
8690
std::vector<std::string> CandidateCompiledModules;
8791

include/swift/Basic/LangOptions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,9 @@ namespace swift {
127127
/// The target variant SDK version, if known.
128128
Optional<llvm::VersionTuple> VariantSDKVersion;
129129

130+
/// The SDK canonical name, if known.
131+
std::string SDKName;
132+
130133
/// The alternate name to use for the entry point instead of main.
131134
std::string entryPointFunctionName = "main";
132135

include/swift/Option/FrontendOptions.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -831,6 +831,9 @@ def target_sdk_version : Separate<["-"], "target-sdk-version">,
831831
def target_variant_sdk_version : Separate<["-"], "target-variant-sdk-version">,
832832
HelpText<"The version of target variant SDK used for compilation">;
833833

834+
def target_sdk_name : Separate<["-"], "target-sdk-name">,
835+
HelpText<"Canonical name of the target SDK used for compilation">;
836+
834837
def extra_clang_options_only : Flag<["-"], "only-use-extra-clang-opts">,
835838
HelpText<"Options passed via -Xcc are sufficient for Clang configuration">;
836839

include/swift/Serialization/SerializationOptions.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ namespace swift {
3535
bool SkipSymbolGraphInheritedDocs = true;
3636
bool IncludeSPISymbolsInSymbolGraph = false;
3737
llvm::VersionTuple UserModuleVersion;
38+
std::string SDKName;
3839

3940
StringRef GroupInfoPath;
4041
StringRef ImportedHeader;

include/swift/Serialization/Validation.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,11 @@ enum class Status {
6666
TargetIncompatible,
6767

6868
/// The module file was built for a target newer than the current target.
69-
TargetTooNew
69+
TargetTooNew,
70+
71+
/// The module file was built with a different SDK than the one in use
72+
/// to build the client.
73+
SDKMismatch
7074
};
7175

7276
/// Returns true if the data looks like it contains a serialized AST.
@@ -80,6 +84,7 @@ struct ValidationInfo {
8084
StringRef miscVersion = {};
8185
version::Version compatibilityVersion = {};
8286
llvm::VersionTuple userModuleVersion;
87+
StringRef sdkName = {};
8388
size_t bytes = 0;
8489
Status status = Status::Malformed;
8590
};

lib/APIDigester/ModuleAnalyzerNodes.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2233,6 +2233,9 @@ swift::ide::api::getSDKNodeRoot(SDKContext &SDKCtx,
22332233

22342234
auto &Ctx = CI.getASTContext();
22352235

2236+
// Don't check if the stdlib was build with the same SDK as what is loaded
2237+
// here as some tests rely on using a different stdlib.
2238+
Ctx.SearchPathOpts.EnableSameSDKCheck = false;
22362239

22372240
// Load standard library so that Clang importer can use it.
22382241
auto *Stdlib = Ctx.getStdlibModule(/*loadIfAbsent=*/true);

lib/Frontend/CompilerInvocation.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -777,6 +777,11 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
777777
}
778778
}
779779

780+
// Get the SDK name.
781+
if (Arg *A = Args.getLastArg(options::OPT_target_sdk_name)) {
782+
Opts.SDKName = A->getValue();
783+
}
784+
780785
if (const Arg *A = Args.getLastArg(OPT_entry_point_function_name)) {
781786
Opts.entryPointFunctionName = A->getValue();
782787
}

lib/Frontend/Frontend.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ SerializationOptions CompilerInvocation::computeSerializationOptions(
150150
serializationOpts.ExtraClangOptions = getClangImporterOptions().ExtraArgs;
151151
serializationOpts.PublicDependentLibraries =
152152
getIRGenOptions().PublicLinkLibraries;
153+
serializationOpts.SDKName = getLangOptions().SDKName;
153154

154155
if (opts.EmitSymbolGraph) {
155156
if (!opts.SymbolGraphOutputDir.empty()) {

lib/Frontend/ModuleInterfaceBuilder.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,8 @@ bool ModuleInterfaceBuilder::buildSwiftModuleInternal(
257257
if (!getRelativeDepPath(InPath, SDKPath))
258258
SerializationOpts.ModuleInterface = InPath;
259259

260+
SerializationOpts.SDKName = SubInstance.getASTContext().LangOpts.SDKName;
261+
260262
SmallVector<FileDependency, 16> Deps;
261263
bool serializeHashes = FEOpts.SerializeModuleInterfaceDependencyHashes;
262264
if (collectDepsForSerialization(SubInstance, Deps, serializeHashes)) {

lib/Serialization/ModuleFile.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,15 @@ Status ModuleFile::associateWithFileContext(FileUnit *file, SourceLoc diagLoc,
149149
return error(status);
150150
}
151151

152+
auto clientSDK = ctx.LangOpts.SDKName;
153+
StringRef moduleSDK = Core->SDKName;
154+
if (ctx.SearchPathOpts.EnableSameSDKCheck &&
155+
!moduleSDK.empty() && !clientSDK.empty() &&
156+
moduleSDK != clientSDK) {
157+
status = Status::SDKMismatch;
158+
return error(status);
159+
}
160+
152161
for (const auto &searchPath : Core->SearchPaths)
153162
ctx.addSearchPath(searchPath.Path, searchPath.IsFramework,
154163
searchPath.IsSystem);

lib/Serialization/ModuleFileSharedCore.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,10 @@ validateControlBlock(llvm::BitstreamCursor &cursor,
299299
case control_block::TARGET:
300300
result.targetTriple = blobData;
301301
break;
302+
case control_block::SDK_NAME: {
303+
result.sdkName = blobData;
304+
break;
305+
}
302306
default:
303307
// Unknown metadata record, possibly for use by a future version of the
304308
// module format.
@@ -1210,6 +1214,7 @@ ModuleFileSharedCore::ModuleFileSharedCore(
12101214
}
12111215
Name = info.name;
12121216
TargetTriple = info.targetTriple;
1217+
SDKName = info.sdkName;
12131218
CompatibilityVersion = info.compatibilityVersion;
12141219
UserModuleVersion = info.userModuleVersion;
12151220
Bits.ArePrivateImportsEnabled = extInfo.arePrivateImportsEnabled();

lib/Serialization/ModuleFileSharedCore.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ class ModuleFileSharedCore {
5858
/// The target the module was built for.
5959
StringRef TargetTriple;
6060

61+
/// The canonical name of the SDK the module was built with.
62+
StringRef SDKName;
63+
6164
/// The name of the module interface this module was compiled from.
6265
///
6366
/// Empty if this module didn't come from an interface file.

lib/Serialization/ModuleFormat.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0;
5656
/// describe what change you made. The content of this comment isn't important;
5757
/// it just ensures a conflict if two people change the module format.
5858
/// Don't worry about adhering to the 80-column limit for this line.
59-
const uint16_t SWIFTMODULE_VERSION_MINOR = 628; // unaligned pointer
59+
const uint16_t SWIFTMODULE_VERSION_MINOR = 629; // BuilderSDK
6060

6161
/// A standard hash seed used for all string hashes in a serialized module.
6262
///
@@ -754,7 +754,8 @@ namespace control_block {
754754
enum {
755755
METADATA = 1,
756756
MODULE_NAME,
757-
TARGET
757+
TARGET,
758+
SDK_NAME
758759
};
759760

760761
using MetadataLayout = BCRecordLayout<
@@ -779,6 +780,11 @@ namespace control_block {
779780
TARGET,
780781
BCBlob // LLVM triple
781782
>;
783+
784+
using SDKNameLayout = BCRecordLayout<
785+
SDK_NAME,
786+
BCBlob
787+
>;
782788
}
783789

784790
/// The record types within the options block (a sub-block of the control

lib/Serialization/Serialization.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -802,6 +802,7 @@ void Serializer::writeBlockInfoBlock() {
802802
BLOCK_RECORD(control_block, METADATA);
803803
BLOCK_RECORD(control_block, MODULE_NAME);
804804
BLOCK_RECORD(control_block, TARGET);
805+
BLOCK_RECORD(control_block, SDK_NAME);
805806

806807
BLOCK(OPTIONS_BLOCK);
807808
BLOCK_RECORD(options_block, SDK_PATH);
@@ -952,6 +953,7 @@ void Serializer::writeHeader(const SerializationOptions &options) {
952953
control_block::ModuleNameLayout ModuleName(Out);
953954
control_block::MetadataLayout Metadata(Out);
954955
control_block::TargetLayout Target(Out);
956+
control_block::SDKNameLayout SDKName(Out);
955957

956958
ModuleName.emit(ScratchRecord, M->getName().str());
957959

@@ -985,6 +987,9 @@ void Serializer::writeHeader(const SerializationOptions &options) {
985987
userModuleSubminor, userModuleBuild,
986988
versionString.str());
987989

990+
if (!options.SDKName.empty())
991+
SDKName.emit(ScratchRecord, options.SDKName);
992+
988993
Target.emit(ScratchRecord, M->getASTContext().LangOpts.Target.str());
989994

990995
{

lib/Serialization/SerializedModuleLoader.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -976,6 +976,13 @@ void swift::serialization::diagnoseSerializedASTLoadFailure(
976976
moduleOSInfo.second, moduleBufferID);
977977
break;
978978
}
979+
980+
case serialization::Status::SDKMismatch:
981+
auto currentSDK = Ctx.LangOpts.SDKName;
982+
auto moduleSDK = loadInfo.sdkName;
983+
Ctx.Diags.diagnose(diagLoc, diag::serialization_sdk_mismatch,
984+
ModuleName, moduleSDK, currentSDK, moduleBufferID);
985+
break;
979986
}
980987
}
981988

test/DebugInfo/compileunit-sysroot-sdk.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-swift-frontend %s -emit-ir -g -o - \
1+
// RUN: %target-swift-frontend %s -emit-ir -g -o - -parse-stdlib \
22
// RUN: -sdk /SWIFT_SYSROOT/MacOSX.sdk | %FileCheck %s
33
// Test that sysroot and SDK are stored in the debug info.
44
// CHECK: distinct !DICompileUnit({{.*}}sysroot: "/SWIFT_SYSROOT/MacOSX.sdk",
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// RUN: %empty-directory(%t/cache)
2+
// RUN: %empty-directory(%t/build)
3+
// RUN: %{python} %utils/split_file.py -o %t %s
4+
5+
/// Build Lib against SDK A.
6+
// RUN: %target-swift-frontend -emit-module %t/Lib.swift -swift-version 5 -target-sdk-name A -o %t/build -parse-stdlib -module-cache-path %t/cache
7+
8+
/// Building Client against SDK A should work fine as expected.
9+
// RUN: %target-swift-frontend -typecheck %t/Client.swift -swift-version 5 -target-sdk-name A -I %t/build -parse-stdlib -module-cache-path %t/cache
10+
11+
/// Build Client against SDK B, this should fail at loading Lib against a different SDK than A.
12+
// RUN: not %target-swift-frontend -typecheck %t/Client.swift -swift-version 5 -target-sdk-name B -I %t/build -parse-stdlib -module-cache-path %t/cache 2>&1 | %FileCheck %s
13+
// CHECK: cannot load module 'Lib' built with SDK 'A' when using SDK 'B': {{.*}}Lib.swiftmodule
14+
15+
// BEGIN Lib.swift
16+
public func foo() {}
17+
18+
// BEGIN Client.swift
19+
import Lib
20+
foo()
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
// swift-interface-format-version: 1.0
22
// swift-tools-version: Apple Swift version 5.1 (swiftlang-1100.0.38 clang-1100.0.20.14)
3-
// swift-module-flags: -target arm64-apple-macos10.14 -enable-objc-interop -enable-library-evolution -swift-version 5 -enforce-exclusivity=checked -O -module-name SwiftFoo
4-
import Swift
3+
// swift-module-flags: -target arm64-apple-macos10.14 -enable-objc-interop -enable-library-evolution -swift-version 5 -enforce-exclusivity=checked -O -module-name SwiftFoo -parse-stdlib
54
public class RemovedClass {
65
@objc deinit
76
}
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
// swift-interface-format-version: 1.0
22
// swift-tools-version: Apple Swift version 5.1 (swiftlang-1100.0.38 clang-1100.0.20.14)
3-
// swift-module-flags: -target x86_64-apple-macos10.14 -enable-objc-interop -enable-library-evolution -swift-version 5 -enforce-exclusivity=checked -O -module-name SwiftFoo
4-
import Swift
3+
// swift-module-flags: -target x86_64-apple-macos10.14 -enable-objc-interop -enable-library-evolution -swift-version 5 -enforce-exclusivity=checked -O -module-name SwiftFoo -parse-stdlib
54
public class RemovedClass {
65
@objc deinit
76
}
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
// swift-interface-format-version: 1.0
22
// swift-tools-version: Apple Swift version 5.1 (swiftlang-1100.0.38 clang-1100.0.20.14)
3-
// swift-module-flags: -target arm64-apple-macos10.14 -enable-objc-interop -enable-library-evolution -swift-version 5 -enforce-exclusivity=checked -O -module-name SwiftFoo
4-
import Swift
3+
// swift-module-flags: -target arm64-apple-macos10.14 -enable-objc-interop -enable-library-evolution -swift-version 5 -enforce-exclusivity=checked -O -module-name SwiftFoo -parse-stdlib
54
public class AddedClass {
65
@objc deinit
76
}
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
// swift-interface-format-version: 1.0
22
// swift-tools-version: Apple Swift version 5.1 (swiftlang-1100.0.38 clang-1100.0.20.14)
3-
// swift-module-flags: -target x86_64-apple-macos10.14 -enable-objc-interop -enable-library-evolution -swift-version 5 -enforce-exclusivity=checked -O -module-name SwiftFoo
4-
import Swift
3+
// swift-module-flags: -target x86_64-apple-macos10.14 -enable-objc-interop -enable-library-evolution -swift-version 5 -enforce-exclusivity=checked -O -module-name SwiftFoo -parse-stdlib
54
public class AddedClass {
65
@objc deinit
76
}

0 commit comments

Comments
 (0)