Skip to content

Commit c8059a0

Browse files
committed
[Serialization] Soft-reject swiftmodules built against a different SDK
Change the way swiftmodules built against a different SDK than their clients are rejected. This makes them silently ignored when the module can be rebuilt from their swiftinterface, instead of reporting a hard error. rdar://93257769
1 parent a63f071 commit c8059a0

File tree

11 files changed

+56
-40
lines changed

11 files changed

+56
-40
lines changed

include/swift/Serialization/Validation.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,13 +196,15 @@ class ExtendedValidationInfo {
196196
/// refers directly into this buffer.
197197
/// \param requiresOSSAModules If true, necessitates the module to be
198198
/// compiled with -enable-ossa-modules.
199+
/// \param requiredSDK If not empty, only accept modules built with
200+
/// a compatible SDK. The StringRef represents the canonical SDK name.
199201
/// \param[out] extendedInfo If present, will be populated with additional
200202
/// compilation options serialized into the AST at build time that may be
201203
/// necessary to load it properly.
202204
/// \param[out] dependencies If present, will be populated with list of
203205
/// input files the module depends on, if present in INPUT_BLOCK.
204206
ValidationInfo validateSerializedAST(
205-
StringRef data, bool requiresOSSAModules,
207+
StringRef data, bool requiresOSSAModules, StringRef requiredSDK,
206208
ExtendedValidationInfo *extendedInfo = nullptr,
207209
SmallVectorImpl<SerializationOptions::FileDependency> *dependencies =
208210
nullptr);

lib/ASTSectionImporter/ASTSectionImporter.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ bool swift::parseASTSection(MemoryBufferSerializedModuleLoader &Loader,
3636
// headers. Iterate over all AST modules.
3737
while (!buf.empty()) {
3838
auto info = serialization::validateSerializedAST(
39-
buf, Loader.isRequiredOSSAModules());
39+
buf, Loader.isRequiredOSSAModules(), /*requiredSDK*/StringRef());
4040

4141
assert(info.name.size() < (2 << 10) && "name failed sanity check");
4242

lib/Frontend/CompilerInvocation.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2522,7 +2522,7 @@ serialization::Status
25222522
CompilerInvocation::loadFromSerializedAST(StringRef data) {
25232523
serialization::ExtendedValidationInfo extendedInfo;
25242524
serialization::ValidationInfo info = serialization::validateSerializedAST(
2525-
data, getSILOptions().EnableOSSAModules, &extendedInfo);
2525+
data, getSILOptions().EnableOSSAModules, LangOpts.SDKName, &extendedInfo);
25262526

25272527
if (info.status != serialization::Status::Valid)
25282528
return info.status;
@@ -2558,7 +2558,7 @@ CompilerInvocation::setUpInputForSILTool(
25582558

25592559
auto result = serialization::validateSerializedAST(
25602560
fileBufOrErr.get()->getBuffer(), getSILOptions().EnableOSSAModules,
2561-
&extendedInfo);
2561+
LangOpts.SDKName, &extendedInfo);
25622562
bool hasSerializedAST = result.status == serialization::Status::Valid;
25632563

25642564
if (hasSerializedAST) {

lib/Frontend/ModuleInterfaceLoader.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -200,9 +200,11 @@ class DiscoveredModule {
200200
namespace path = llvm::sys::path;
201201

202202
static bool serializedASTLooksValid(const llvm::MemoryBuffer &buf,
203-
bool requiresOSSAModules) {
203+
bool requiresOSSAModules,
204+
StringRef requiredSDK) {
204205
auto VI = serialization::validateSerializedAST(buf.getBuffer(),
205-
requiresOSSAModules);
206+
requiresOSSAModules,
207+
requiredSDK);
206208
return VI.status == serialization::Status::Valid;
207209
}
208210

@@ -500,7 +502,7 @@ class ModuleInterfaceLoaderImpl {
500502

501503
LLVM_DEBUG(llvm::dbgs() << "Validating deps of " << path << "\n");
502504
auto validationInfo = serialization::validateSerializedAST(
503-
buf.getBuffer(), requiresOSSAModules,
505+
buf.getBuffer(), requiresOSSAModules, ctx.LangOpts.SDKName,
504506
/*ExtendedValidationInfo=*/nullptr, &allDeps);
505507

506508
if (validationInfo.status != serialization::Status::Valid) {
@@ -542,7 +544,8 @@ class ModuleInterfaceLoaderImpl {
542544

543545
// First, make sure the underlying module path exists and is valid.
544546
auto modBuf = fs.getBufferForFile(fwd.underlyingModulePath);
545-
if (!modBuf || !serializedASTLooksValid(*modBuf.get(), requiresOSSAModules))
547+
if (!modBuf || !serializedASTLooksValid(*modBuf.get(), requiresOSSAModules,
548+
ctx.LangOpts.SDKName))
546549
return false;
547550

548551
// Next, check the dependencies in the forwarding file.

lib/Serialization/ModuleFile.cpp

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -156,22 +156,6 @@ Status ModuleFile::associateWithFileContext(FileUnit *file, SourceLoc diagLoc,
156156
return error(status);
157157
}
158158

159-
// The loaded module was built with a compatible SDK if either:
160-
// * it was the same SDK
161-
// * or one who's name is a prefix of the clients' SDK name. This expects
162-
// that a module built with macOS11 can be used with the macOS11.secret SDK.
163-
// This is generally the case as SDKs with suffixes are a superset of the
164-
// short SDK name equivalent. While this is accepted, this is still not a
165-
// recommended configuration and may lead to unreadable swiftmodules.
166-
StringRef moduleSDK = Core->SDKName;
167-
StringRef clientSDK = ctx.LangOpts.SDKName;
168-
if (ctx.SearchPathOpts.EnableSameSDKCheck &&
169-
!moduleSDK.empty() && !clientSDK.empty() &&
170-
!clientSDK.startswith(moduleSDK)) {
171-
status = Status::SDKMismatch;
172-
return error(status);
173-
}
174-
175159
StringRef SDKPath = ctx.SearchPathOpts.getSDKPath();
176160
if (SDKPath.empty() ||
177161
!Core->ModuleInputBuffer->getBufferIdentifier().startswith(SDKPath)) {
@@ -372,7 +356,7 @@ ModuleFile::getModuleName(ASTContext &Ctx, StringRef modulePath,
372356
bool isFramework = false;
373357
serialization::ValidationInfo loadInfo = ModuleFileSharedCore::load(
374358
modulePath.str(), std::move(newBuf), nullptr, nullptr,
375-
/*isFramework*/ isFramework, Ctx.SILOpts.EnableOSSAModules,
359+
/*isFramework*/ isFramework, Ctx.SILOpts.EnableOSSAModules, Ctx.LangOpts.SDKName,
376360
Ctx.SearchPathOpts.DeserializedPathRecoverer,
377361
loadedModuleFile);
378362
Name = loadedModuleFile->Name.str();

lib/Serialization/ModuleFileSharedCore.cpp

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ static ValidationInfo validateControlBlock(
173173
llvm::BitstreamCursor &cursor, SmallVectorImpl<uint64_t> &scratch,
174174
std::pair<uint16_t, uint16_t> expectedVersion, bool requiresOSSAModules,
175175
bool requiresRevisionMatch,
176+
StringRef requiredSDK,
176177
ExtendedValidationInfo *extendedInfo,
177178
PathObfuscator &pathRecoverer) {
178179
// The control block is malformed until we've at least read a major version
@@ -307,6 +308,21 @@ static ValidationInfo validateControlBlock(
307308
break;
308309
case control_block::SDK_NAME: {
309310
result.sdkName = blobData;
311+
312+
// The loaded module was built with a compatible SDK if either:
313+
// * it was the same SDK
314+
// * or one who's name is a prefix of the clients' SDK name. This expects
315+
// that a module built with macOS11 can be used with the macOS11.secret SDK.
316+
// This is generally the case as SDKs with suffixes are a superset of the
317+
// short SDK name equivalent. While this is accepted, this is still not a
318+
// recommended configuration and may lead to unreadable swiftmodules.
319+
StringRef moduleSDK = blobData;
320+
if (!moduleSDK.empty() && !requiredSDK.empty() &&
321+
!requiredSDK.startswith(moduleSDK)) {
322+
result.status = Status::SDKMismatch;
323+
return result;
324+
}
325+
310326
break;
311327
}
312328
case control_block::REVISION: {
@@ -443,7 +459,7 @@ bool serialization::isSerializedAST(StringRef data) {
443459
}
444460

445461
ValidationInfo serialization::validateSerializedAST(
446-
StringRef data, bool requiresOSSAModules,
462+
StringRef data, bool requiresOSSAModules, StringRef requiredSDK,
447463
ExtendedValidationInfo *extendedInfo,
448464
SmallVectorImpl<SerializationOptions::FileDependency> *dependencies) {
449465
ValidationInfo result;
@@ -487,6 +503,7 @@ ValidationInfo serialization::validateSerializedAST(
487503
cursor, scratch,
488504
{SWIFTMODULE_VERSION_MAJOR, SWIFTMODULE_VERSION_MINOR},
489505
requiresOSSAModules, /*requiresRevisionMatch=*/true,
506+
requiredSDK,
490507
extendedInfo, localObfuscator);
491508
if (result.status == Status::Malformed)
492509
return result;
@@ -995,8 +1012,8 @@ bool ModuleFileSharedCore::readModuleDocIfPresent(PathObfuscator &pathRecoverer)
9951012

9961013
info = validateControlBlock(
9971014
docCursor, scratch, {SWIFTDOC_VERSION_MAJOR, SWIFTDOC_VERSION_MINOR},
998-
RequiresOSSAModules, /*requiresRevisionMatch=*/false,
999-
/*extendedInfo*/ nullptr, pathRecoverer);
1015+
RequiresOSSAModules, /*requiresRevisionMatch*/false,
1016+
/*requiredSDK*/StringRef(), /*extendedInfo*/nullptr, pathRecoverer);
10001017
if (info.status != Status::Valid)
10011018
return false;
10021019
// Check that the swiftdoc is actually for this module.
@@ -1139,9 +1156,8 @@ bool ModuleFileSharedCore::readModuleSourceInfoIfPresent(PathObfuscator &pathRec
11391156
info = validateControlBlock(
11401157
infoCursor, scratch,
11411158
{SWIFTSOURCEINFO_VERSION_MAJOR, SWIFTSOURCEINFO_VERSION_MINOR},
1142-
RequiresOSSAModules, /*requiresRevisionMatch=*/false,
1143-
/*extendedInfo*/ nullptr,
1144-
pathRecoverer);
1159+
RequiresOSSAModules, /*requiresRevisionMatch*/false,
1160+
/*requiredSDK*/StringRef(), /*extendedInfo*/nullptr, pathRecoverer);
11451161
if (info.status != Status::Valid)
11461162
return false;
11471163
// Check that the swiftsourceinfo is actually for this module.
@@ -1215,7 +1231,7 @@ ModuleFileSharedCore::ModuleFileSharedCore(
12151231
std::unique_ptr<llvm::MemoryBuffer> moduleInputBuffer,
12161232
std::unique_ptr<llvm::MemoryBuffer> moduleDocInputBuffer,
12171233
std::unique_ptr<llvm::MemoryBuffer> moduleSourceInfoInputBuffer,
1218-
bool isFramework, bool requiresOSSAModules,
1234+
bool isFramework, bool requiresOSSAModules, StringRef requiredSDK,
12191235
serialization::ValidationInfo &info, PathObfuscator &pathRecoverer)
12201236
: ModuleInputBuffer(std::move(moduleInputBuffer)),
12211237
ModuleDocInputBuffer(std::move(moduleDocInputBuffer)),
@@ -1267,7 +1283,7 @@ ModuleFileSharedCore::ModuleFileSharedCore(
12671283
info = validateControlBlock(
12681284
cursor, scratch,
12691285
{SWIFTMODULE_VERSION_MAJOR, SWIFTMODULE_VERSION_MINOR},
1270-
RequiresOSSAModules, /*requiresRevisionMatch=*/true,
1286+
RequiresOSSAModules, /*requiresRevisionMatch=*/true, requiredSDK,
12711287
&extInfo, pathRecoverer);
12721288
if (info.status != Status::Valid) {
12731289
error(info.status);

lib/Serialization/ModuleFileSharedCore.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,7 @@ class ModuleFileSharedCore {
373373
std::unique_ptr<llvm::MemoryBuffer> moduleInputBuffer,
374374
std::unique_ptr<llvm::MemoryBuffer> moduleDocInputBuffer,
375375
std::unique_ptr<llvm::MemoryBuffer> moduleSourceInfoInputBuffer,
376-
bool isFramework, bool requiresOSSAModules,
376+
bool isFramework, bool requiresOSSAModules, StringRef requiredSDK,
377377
serialization::ValidationInfo &info, PathObfuscator &pathRecoverer);
378378

379379
/// Change the status of the current module.
@@ -510,13 +510,13 @@ class ModuleFileSharedCore {
510510
std::unique_ptr<llvm::MemoryBuffer> moduleDocInputBuffer,
511511
std::unique_ptr<llvm::MemoryBuffer> moduleSourceInfoInputBuffer,
512512
bool isFramework, bool requiresOSSAModules,
513-
PathObfuscator &pathRecoverer,
513+
StringRef requiredSDK, PathObfuscator &pathRecoverer,
514514
std::shared_ptr<const ModuleFileSharedCore> &theModule) {
515515
serialization::ValidationInfo info;
516516
auto *core = new ModuleFileSharedCore(
517517
std::move(moduleInputBuffer), std::move(moduleDocInputBuffer),
518518
std::move(moduleSourceInfoInputBuffer), isFramework,
519-
requiresOSSAModules, info, pathRecoverer);
519+
requiresOSSAModules, requiredSDK, info, pathRecoverer);
520520
if (!moduleInterfacePath.empty()) {
521521
ArrayRef<char> path;
522522
core->allocateBuffer(path, moduleInterfacePath);

lib/Serialization/SerializedModuleLoader.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,7 @@ llvm::ErrorOr<ModuleDependencies> SerializedModuleLoaderBase::scanModuleFile(
402402
bool isFramework = false;
403403
serialization::ValidationInfo loadInfo = ModuleFileSharedCore::load(
404404
modulePath.str(), std::move(moduleBuf.get()), nullptr, nullptr,
405-
isFramework, isRequiredOSSAModules(),
405+
isFramework, isRequiredOSSAModules(), Ctx.LangOpts.SDKName,
406406
Ctx.SearchPathOpts.DeserializedPathRecoverer,
407407
loadedModuleFile);
408408

@@ -753,7 +753,7 @@ LoadedFile *SerializedModuleLoaderBase::loadAST(
753753
serialization::ValidationInfo loadInfo = ModuleFileSharedCore::load(
754754
moduleInterfacePath, std::move(moduleInputBuffer),
755755
std::move(moduleDocInputBuffer), std::move(moduleSourceInfoInputBuffer),
756-
isFramework, isRequiredOSSAModules(),
756+
isFramework, isRequiredOSSAModules(), Ctx.LangOpts.SDKName,
757757
Ctx.SearchPathOpts.DeserializedPathRecoverer,
758758
loadedModuleFileCore);
759759
SerializedASTFile *fileUnit = nullptr;
@@ -1176,7 +1176,8 @@ bool SerializedModuleLoaderBase::canImportModule(ImportPath::Module path,
11761176
// format, if present.
11771177
if (currentVersion.empty() && *unusedModuleBuffer) {
11781178
auto metaData = serialization::validateSerializedAST(
1179-
(*unusedModuleBuffer)->getBuffer(), Ctx.SILOpts.EnableOSSAModules);
1179+
(*unusedModuleBuffer)->getBuffer(), Ctx.SILOpts.EnableOSSAModules,
1180+
Ctx.LangOpts.SDKName);
11801181
currentVersion = metaData.userModuleVersion;
11811182
}
11821183

test/Serialization/restrict-swiftmodule-to-sdk.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,15 @@
2020
// RUN: not %target-swift-frontend -typecheck %t/Client.swift -swift-version 5 -target-sdk-name C -I %t/build -parse-stdlib -module-cache-path %t/cache 2>&1 | %FileCheck %s -check-prefix=CHECK-C
2121
// CHECK-C: cannot load module 'Lib' built with SDK 'C.Secret' when using SDK 'C': {{.*}}Lib.swiftmodule
2222

23+
/// Build a resilient Lib against SDK A, and a client against SDK B.
24+
/// This should succeed after rebuilding from the swiftinterface.
25+
// RUN: %empty-directory(%t/cache)
26+
// 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 \
27+
// RUN: -enable-library-evolution -emit-module-interface-path %t/build/Lib.swiftinterface
28+
// RUN: %target-swift-frontend -typecheck %t/Client.swift -swift-version 5 -target-sdk-name B -I %t/build -parse-stdlib -module-cache-path %t/cache \
29+
// RUN: -Rmodule-interface-rebuild 2>&1 | %FileCheck %s -check-prefix=CHECK-AvsB-REBUILD
30+
// CHECK-AvsB-REBUILD: remark: rebuilding module 'Lib' from interface
31+
2332
// BEGIN Lib.swift
2433
public func foo() {}
2534

tools/lldb-moduleimport-test/lldb-moduleimport-test.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ validateModule(llvm::StringRef data, bool Verbose, bool requiresOSSAModules,
4949
swift::serialization::ValidationInfo &info,
5050
swift::serialization::ExtendedValidationInfo &extendedInfo) {
5151
info = swift::serialization::validateSerializedAST(data, requiresOSSAModules,
52+
/*requiredSDK*/StringRef(),
5253
&extendedInfo);
5354
if (info.status != swift::serialization::Status::Valid) {
5455
llvm::outs() << "error: validateSerializedAST() failed\n";

unittests/FrontendTool/ModuleLoadingTests.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ class ModuleInterfaceLoaderTest : public testing::Test {
149149

150150
auto bufData = (*bufOrErr)->getBuffer();
151151
auto validationInfo = serialization::validateSerializedAST(
152-
bufData, silOpts.EnableOSSAModules);
152+
bufData, silOpts.EnableOSSAModules, /*requiredSDK*/StringRef());
153153
ASSERT_EQ(serialization::Status::Valid, validationInfo.status);
154154
ASSERT_EQ(bufData, moduleBuffer->getBuffer());
155155
}

0 commit comments

Comments
 (0)