[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
This commit is contained in:
Alexis Laferrière
2022-05-11 09:09:14 -07:00
parent a63f071ea2
commit c8059a09e9
11 changed files with 56 additions and 40 deletions

View File

@@ -156,22 +156,6 @@ Status ModuleFile::associateWithFileContext(FileUnit *file, SourceLoc diagLoc,
return error(status);
}
// The loaded module was built with a compatible SDK if either:
// * it was the same SDK
// * or one who's name is a prefix of the clients' SDK name. This expects
// that a module built with macOS11 can be used with the macOS11.secret SDK.
// This is generally the case as SDKs with suffixes are a superset of the
// short SDK name equivalent. While this is accepted, this is still not a
// recommended configuration and may lead to unreadable swiftmodules.
StringRef moduleSDK = Core->SDKName;
StringRef clientSDK = ctx.LangOpts.SDKName;
if (ctx.SearchPathOpts.EnableSameSDKCheck &&
!moduleSDK.empty() && !clientSDK.empty() &&
!clientSDK.startswith(moduleSDK)) {
status = Status::SDKMismatch;
return error(status);
}
StringRef SDKPath = ctx.SearchPathOpts.getSDKPath();
if (SDKPath.empty() ||
!Core->ModuleInputBuffer->getBufferIdentifier().startswith(SDKPath)) {
@@ -372,7 +356,7 @@ ModuleFile::getModuleName(ASTContext &Ctx, StringRef modulePath,
bool isFramework = false;
serialization::ValidationInfo loadInfo = ModuleFileSharedCore::load(
modulePath.str(), std::move(newBuf), nullptr, nullptr,
/*isFramework*/ isFramework, Ctx.SILOpts.EnableOSSAModules,
/*isFramework*/ isFramework, Ctx.SILOpts.EnableOSSAModules, Ctx.LangOpts.SDKName,
Ctx.SearchPathOpts.DeserializedPathRecoverer,
loadedModuleFile);
Name = loadedModuleFile->Name.str();

View File

@@ -173,6 +173,7 @@ static ValidationInfo validateControlBlock(
llvm::BitstreamCursor &cursor, SmallVectorImpl<uint64_t> &scratch,
std::pair<uint16_t, uint16_t> expectedVersion, bool requiresOSSAModules,
bool requiresRevisionMatch,
StringRef requiredSDK,
ExtendedValidationInfo *extendedInfo,
PathObfuscator &pathRecoverer) {
// The control block is malformed until we've at least read a major version
@@ -307,6 +308,21 @@ static ValidationInfo validateControlBlock(
break;
case control_block::SDK_NAME: {
result.sdkName = blobData;
// The loaded module was built with a compatible SDK if either:
// * it was the same SDK
// * or one who's name is a prefix of the clients' SDK name. This expects
// that a module built with macOS11 can be used with the macOS11.secret SDK.
// This is generally the case as SDKs with suffixes are a superset of the
// short SDK name equivalent. While this is accepted, this is still not a
// recommended configuration and may lead to unreadable swiftmodules.
StringRef moduleSDK = blobData;
if (!moduleSDK.empty() && !requiredSDK.empty() &&
!requiredSDK.startswith(moduleSDK)) {
result.status = Status::SDKMismatch;
return result;
}
break;
}
case control_block::REVISION: {
@@ -443,7 +459,7 @@ bool serialization::isSerializedAST(StringRef data) {
}
ValidationInfo serialization::validateSerializedAST(
StringRef data, bool requiresOSSAModules,
StringRef data, bool requiresOSSAModules, StringRef requiredSDK,
ExtendedValidationInfo *extendedInfo,
SmallVectorImpl<SerializationOptions::FileDependency> *dependencies) {
ValidationInfo result;
@@ -487,6 +503,7 @@ ValidationInfo serialization::validateSerializedAST(
cursor, scratch,
{SWIFTMODULE_VERSION_MAJOR, SWIFTMODULE_VERSION_MINOR},
requiresOSSAModules, /*requiresRevisionMatch=*/true,
requiredSDK,
extendedInfo, localObfuscator);
if (result.status == Status::Malformed)
return result;
@@ -995,8 +1012,8 @@ bool ModuleFileSharedCore::readModuleDocIfPresent(PathObfuscator &pathRecoverer)
info = validateControlBlock(
docCursor, scratch, {SWIFTDOC_VERSION_MAJOR, SWIFTDOC_VERSION_MINOR},
RequiresOSSAModules, /*requiresRevisionMatch=*/false,
/*extendedInfo*/ nullptr, pathRecoverer);
RequiresOSSAModules, /*requiresRevisionMatch*/false,
/*requiredSDK*/StringRef(), /*extendedInfo*/nullptr, pathRecoverer);
if (info.status != Status::Valid)
return false;
// Check that the swiftdoc is actually for this module.
@@ -1139,9 +1156,8 @@ bool ModuleFileSharedCore::readModuleSourceInfoIfPresent(PathObfuscator &pathRec
info = validateControlBlock(
infoCursor, scratch,
{SWIFTSOURCEINFO_VERSION_MAJOR, SWIFTSOURCEINFO_VERSION_MINOR},
RequiresOSSAModules, /*requiresRevisionMatch=*/false,
/*extendedInfo*/ nullptr,
pathRecoverer);
RequiresOSSAModules, /*requiresRevisionMatch*/false,
/*requiredSDK*/StringRef(), /*extendedInfo*/nullptr, pathRecoverer);
if (info.status != Status::Valid)
return false;
// Check that the swiftsourceinfo is actually for this module.
@@ -1215,7 +1231,7 @@ ModuleFileSharedCore::ModuleFileSharedCore(
std::unique_ptr<llvm::MemoryBuffer> moduleInputBuffer,
std::unique_ptr<llvm::MemoryBuffer> moduleDocInputBuffer,
std::unique_ptr<llvm::MemoryBuffer> moduleSourceInfoInputBuffer,
bool isFramework, bool requiresOSSAModules,
bool isFramework, bool requiresOSSAModules, StringRef requiredSDK,
serialization::ValidationInfo &info, PathObfuscator &pathRecoverer)
: ModuleInputBuffer(std::move(moduleInputBuffer)),
ModuleDocInputBuffer(std::move(moduleDocInputBuffer)),
@@ -1267,7 +1283,7 @@ ModuleFileSharedCore::ModuleFileSharedCore(
info = validateControlBlock(
cursor, scratch,
{SWIFTMODULE_VERSION_MAJOR, SWIFTMODULE_VERSION_MINOR},
RequiresOSSAModules, /*requiresRevisionMatch=*/true,
RequiresOSSAModules, /*requiresRevisionMatch=*/true, requiredSDK,
&extInfo, pathRecoverer);
if (info.status != Status::Valid) {
error(info.status);

View File

@@ -373,7 +373,7 @@ private:
std::unique_ptr<llvm::MemoryBuffer> moduleInputBuffer,
std::unique_ptr<llvm::MemoryBuffer> moduleDocInputBuffer,
std::unique_ptr<llvm::MemoryBuffer> moduleSourceInfoInputBuffer,
bool isFramework, bool requiresOSSAModules,
bool isFramework, bool requiresOSSAModules, StringRef requiredSDK,
serialization::ValidationInfo &info, PathObfuscator &pathRecoverer);
/// Change the status of the current module.
@@ -510,13 +510,13 @@ public:
std::unique_ptr<llvm::MemoryBuffer> moduleDocInputBuffer,
std::unique_ptr<llvm::MemoryBuffer> moduleSourceInfoInputBuffer,
bool isFramework, bool requiresOSSAModules,
PathObfuscator &pathRecoverer,
StringRef requiredSDK, PathObfuscator &pathRecoverer,
std::shared_ptr<const ModuleFileSharedCore> &theModule) {
serialization::ValidationInfo info;
auto *core = new ModuleFileSharedCore(
std::move(moduleInputBuffer), std::move(moduleDocInputBuffer),
std::move(moduleSourceInfoInputBuffer), isFramework,
requiresOSSAModules, info, pathRecoverer);
requiresOSSAModules, requiredSDK, info, pathRecoverer);
if (!moduleInterfacePath.empty()) {
ArrayRef<char> path;
core->allocateBuffer(path, moduleInterfacePath);

View File

@@ -402,7 +402,7 @@ llvm::ErrorOr<ModuleDependencies> SerializedModuleLoaderBase::scanModuleFile(
bool isFramework = false;
serialization::ValidationInfo loadInfo = ModuleFileSharedCore::load(
modulePath.str(), std::move(moduleBuf.get()), nullptr, nullptr,
isFramework, isRequiredOSSAModules(),
isFramework, isRequiredOSSAModules(), Ctx.LangOpts.SDKName,
Ctx.SearchPathOpts.DeserializedPathRecoverer,
loadedModuleFile);
@@ -753,7 +753,7 @@ LoadedFile *SerializedModuleLoaderBase::loadAST(
serialization::ValidationInfo loadInfo = ModuleFileSharedCore::load(
moduleInterfacePath, std::move(moduleInputBuffer),
std::move(moduleDocInputBuffer), std::move(moduleSourceInfoInputBuffer),
isFramework, isRequiredOSSAModules(),
isFramework, isRequiredOSSAModules(), Ctx.LangOpts.SDKName,
Ctx.SearchPathOpts.DeserializedPathRecoverer,
loadedModuleFileCore);
SerializedASTFile *fileUnit = nullptr;
@@ -1176,7 +1176,8 @@ bool SerializedModuleLoaderBase::canImportModule(ImportPath::Module path,
// format, if present.
if (currentVersion.empty() && *unusedModuleBuffer) {
auto metaData = serialization::validateSerializedAST(
(*unusedModuleBuffer)->getBuffer(), Ctx.SILOpts.EnableOSSAModules);
(*unusedModuleBuffer)->getBuffer(), Ctx.SILOpts.EnableOSSAModules,
Ctx.LangOpts.SDKName);
currentVersion = metaData.userModuleVersion;
}