diff options
author | Carlos Sanchez <1175054+carlossanlop@users.noreply.github.com> | 2022-11-11 05:45:06 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-11-11 05:45:06 +0300 |
commit | ef994e48ea3e4b7aa650d0d6cc6421b0726f6ce0 (patch) | |
tree | c6be104666da9cb2bf673a846ca981e1f68dd7a1 | |
parent | aebb541ea46e4350764b8975dfffa92b88eac7c7 (diff) | |
parent | 9dd2bbcfa46fa4650379ceeba7781f41cfc0e273 (diff) |
Merge branch 'release/7.0' into darc-release/7.0-88d4fa90-5b62-4f24-9b34-817e68929c2adarc-release/7.0-88d4fa90-5b62-4f24-9b34-817e68929c2a
23 files changed, 347 insertions, 113 deletions
diff --git a/NuGet.config b/NuGet.config index 6e0d6bf716f..4d71005a68c 100644 --- a/NuGet.config +++ b/NuGet.config @@ -9,6 +9,7 @@ <clear /> <!--Begin: Package sources managed by Dependency Flow automation. Do not edit the sources below.--> <!-- Begin: Package sources from dotnet-emsdk --> + <add key="darc-pub-dotnet-emsdk-3a6c724" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/darc-pub-dotnet-emsdk-3a6c724f/nuget/v3/index.json" /> <!-- End: Package sources from dotnet-emsdk --> <!--End: Package sources managed by Dependency Flow automation. Do not edit the sources above.--> <!-- diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index fd65daac7c3..addee73f6f0 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -48,13 +48,13 @@ <Uri>https://github.com/dotnet/command-line-api</Uri> <Sha>5618b2d243ccdeb5c7e50a298b33b13036b4351b</Sha> </Dependency> - <Dependency Name="Microsoft.NET.Workload.Emscripten.net6.Manifest-7.0.100" Version="7.0.0"> + <Dependency Name="Microsoft.NET.Workload.Emscripten.net6.Manifest-7.0.100" Version="7.0.1"> <Uri>https://github.com/dotnet/emsdk</Uri> - <Sha>6b7d1f47eaaa3f64c95e6f825c9e57debd4c0f31</Sha> + <Sha>3a6c724f1915748d1ebbf8c14e99dc04ae6a295d</Sha> </Dependency> - <Dependency Name="Microsoft.NET.Workload.Emscripten.net7.Manifest-7.0.100" Version="7.0.0"> + <Dependency Name="Microsoft.NET.Workload.Emscripten.net7.Manifest-7.0.100" Version="7.0.1"> <Uri>https://github.com/dotnet/emsdk</Uri> - <Sha>6b7d1f47eaaa3f64c95e6f825c9e57debd4c0f31</Sha> + <Sha>3a6c724f1915748d1ebbf8c14e99dc04ae6a295d</Sha> </Dependency> </ProductDependencies> <ToolsetDependencies> diff --git a/eng/Versions.props b/eng/Versions.props index d0b1e2c37a0..a8ecc499e31 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -23,8 +23,8 @@ <UsingToolXliff>false</UsingToolXliff> <LastReleasedStableAssemblyVersion>$(AssemblyVersion)</LastReleasedStableAssemblyVersion> <UsingToolMicrosoftNetCompilers>true</UsingToolMicrosoftNetCompilers> - <MicrosoftNETWorkloadEmscriptennet6Manifest70100Version>7.0.0</MicrosoftNETWorkloadEmscriptennet6Manifest70100Version> - <MicrosoftNETWorkloadEmscriptennet7Manifest70100Version>7.0.0</MicrosoftNETWorkloadEmscriptennet7Manifest70100Version> + <MicrosoftNETWorkloadEmscriptennet6Manifest70100Version>7.0.1</MicrosoftNETWorkloadEmscriptennet6Manifest70100Version> + <MicrosoftNETWorkloadEmscriptennet7Manifest70100Version>7.0.1</MicrosoftNETWorkloadEmscriptennet7Manifest70100Version> </PropertyGroup> <!-- For source generator support we need to target multiple versions of Roslyn in order to be able to run on older versions of Roslyn. diff --git a/src/coreclr/jit/emit.h b/src/coreclr/jit/emit.h index c5d245ba83c..92fb93df931 100644 --- a/src/coreclr/jit/emit.h +++ b/src/coreclr/jit/emit.h @@ -2179,6 +2179,20 @@ private: instrDesc* emitLastIns; + // Check if a peephole optimization involving emitLastIns is safe. + // + // We must have a lastInstr to consult. + // The emitForceNewIG check here prevents peepholes from crossing nogc boundaries. + // The final check prevents looking across an IG boundary unless we're in an extension IG. + bool emitCanPeepholeLastIns() + { + return (emitLastIns != nullptr) && // there is an emitLastInstr + !emitForceNewIG && // and we're not about to start a new IG + ((emitCurIGinsCnt > 0) || // and we're not at the start of a new IG + ((emitCurIG->igFlags & IGF_EXTEND) != 0)); // or we are at the start of a new IG, + // and it's an extension IG + } + #ifdef TARGET_ARMARCH instrDesc* emitLastMemBarrier; #endif diff --git a/src/coreclr/jit/emitarm64.cpp b/src/coreclr/jit/emitarm64.cpp index 499b0470ff2..f94c703ed39 100644 --- a/src/coreclr/jit/emitarm64.cpp +++ b/src/coreclr/jit/emitarm64.cpp @@ -15940,7 +15940,7 @@ bool emitter::IsRedundantMov(instruction ins, emitAttr size, regNumber dst, regN return false; } - const bool isFirstInstrInBlock = (emitCurIGinsCnt == 0) && ((emitCurIG->igFlags & IGF_EXTEND) == 0); + const bool canOptimize = emitCanPeepholeLastIns(); if (dst == src) { @@ -15960,8 +15960,8 @@ bool emitter::IsRedundantMov(instruction ins, emitAttr size, regNumber dst, regN else if (isGeneralRegisterOrSP(dst) && (size == EA_4BYTE)) { // See if the previous instruction already cleared upper 4 bytes for us unintentionally - if (!isFirstInstrInBlock && (emitLastIns != nullptr) && (emitLastIns->idReg1() == dst) && - (emitLastIns->idOpSize() == size) && emitLastIns->idInsIs(INS_ldr, INS_ldrh, INS_ldrb)) + if (canOptimize && (emitLastIns->idReg1() == dst) && (emitLastIns->idOpSize() == size) && + emitLastIns->idInsIs(INS_ldr, INS_ldrh, INS_ldrb)) { JITDUMP("\n -- suppressing mov because ldr already cleared upper 4 bytes\n"); return true; @@ -15969,8 +15969,7 @@ bool emitter::IsRedundantMov(instruction ins, emitAttr size, regNumber dst, regN } } - if (!isFirstInstrInBlock && // Don't optimize if instruction is not the first instruction in IG. - (emitLastIns != nullptr) && + if (canOptimize && // Don't optimize if unsafe. (emitLastIns->idIns() == INS_mov) && // Don't optimize if last instruction was not 'mov'. (emitLastIns->idOpSize() == size)) // Don't optimize if operand size is different than previous instruction. { @@ -16048,9 +16047,7 @@ bool emitter::IsRedundantMov(instruction ins, emitAttr size, regNumber dst, regN bool emitter::IsRedundantLdStr( instruction ins, regNumber reg1, regNumber reg2, ssize_t imm, emitAttr size, insFormat fmt) { - bool isFirstInstrInBlock = (emitCurIGinsCnt == 0) && ((emitCurIG->igFlags & IGF_EXTEND) == 0); - - if (((ins != INS_ldr) && (ins != INS_str)) || (isFirstInstrInBlock) || (emitLastIns == nullptr)) + if (((ins != INS_ldr) && (ins != INS_str)) || !emitCanPeepholeLastIns()) { return false; } diff --git a/src/coreclr/jit/emitxarch.cpp b/src/coreclr/jit/emitxarch.cpp index cbba666f80e..86cf648e730 100644 --- a/src/coreclr/jit/emitxarch.cpp +++ b/src/coreclr/jit/emitxarch.cpp @@ -314,10 +314,9 @@ bool emitter::IsFlagsAlwaysModified(instrDesc* id) bool emitter::AreUpper32BitsZero(regNumber reg) { - // If there are no instructions in this IG, we can look back at - // the previous IG's instructions if this IG is an extension. + // Only consider if safe // - if ((emitCurIGinsCnt == 0) && ((emitCurIG->igFlags & IGF_EXTEND) == 0)) + if (!emitCanPeepholeLastIns()) { return false; } @@ -397,8 +396,9 @@ bool emitter::AreFlagsSetToZeroCmp(regNumber reg, emitAttr opSize, genTreeOps tr return false; } - // Don't look back across IG boundaries (possible control flow) - if (emitCurIGinsCnt == 0 && ((emitCurIG->igFlags & IGF_EXTEND) == 0)) + // Only consider if safe + // + if (!emitCanPeepholeLastIns()) { return false; } @@ -480,8 +480,9 @@ bool emitter::AreFlagsSetForSignJumpOpt(regNumber reg, emitAttr opSize, GenTree* return false; } - // Don't look back across IG boundaries (possible control flow) - if (emitCurIGinsCnt == 0 && ((emitCurIG->igFlags & IGF_EXTEND) == 0)) + // Only consider if safe + // + if (!emitCanPeepholeLastIns()) { return false; } @@ -4698,13 +4699,10 @@ bool emitter::IsRedundantMov( return true; } - bool isFirstInstrInBlock = (emitCurIGinsCnt == 0) && ((emitCurIG->igFlags & IGF_EXTEND) == 0); - // TODO-XArch-CQ: Certain instructions, such as movaps vs movups, are equivalent in // functionality even if their actual identifier differs and we should optimize these - if (isFirstInstrInBlock || // Don't optimize if instruction is the first instruction in IG. - (emitLastIns == nullptr) || // or if a last instruction doesn't exist + if (!emitCanPeepholeLastIns() || // Don't optimize if unsafe (emitLastIns->idIns() != ins) || // or if the instruction is different from the last instruction (emitLastIns->idOpSize() != size) || // or if the operand size is different from the last instruction (emitLastIns->idInsFmt() != fmt)) // or if the format is different from the last instruction @@ -7343,14 +7341,10 @@ bool emitter::IsRedundantStackMov(instruction ins, insFormat fmt, emitAttr size, return false; } - bool hasSideEffect = HasSideEffect(ins, size); - - bool isFirstInstrInBlock = (emitCurIGinsCnt == 0) && ((emitCurIG->igFlags & IGF_EXTEND) == 0); // TODO-XArch-CQ: Certain instructions, such as movaps vs movups, are equivalent in // functionality even if their actual identifier differs and we should optimize these - if (isFirstInstrInBlock || // Don't optimize if instruction is the first instruction in IG. - (emitLastIns == nullptr) || // or if a last instruction doesn't exist + if (!emitCanPeepholeLastIns() || // Don't optimize if unsafe (emitLastIns->idIns() != ins) || // or if the instruction is different from the last instruction (emitLastIns->idOpSize() != size)) // or if the operand size is different from the last instruction { @@ -7367,6 +7361,8 @@ bool emitter::IsRedundantStackMov(instruction ins, insFormat fmt, emitAttr size, int varNum = emitLastIns->idAddr()->iiaLclVar.lvaVarNum(); int lastOffs = emitLastIns->idAddr()->iiaLclVar.lvaOffset(); + const bool hasSideEffect = HasSideEffect(ins, size); + // Check if the last instruction and current instructions use the same register and local memory. if (varNum == varx && lastReg1 == ireg && lastOffs == offs) { diff --git a/src/coreclr/pal/src/include/pal/sharedmemory.h b/src/coreclr/pal/src/include/pal/sharedmemory.h index 88834b93d06..cbdd816dcf2 100644 --- a/src/coreclr/pal/src/include/pal/sharedmemory.h +++ b/src/coreclr/pal/src/include/pal/sharedmemory.h @@ -88,9 +88,11 @@ public: class SharedMemoryHelpers { private: + static const mode_t PermissionsMask_CurrentUser_ReadWrite; static const mode_t PermissionsMask_CurrentUser_ReadWriteExecute; static const mode_t PermissionsMask_AllUsers_ReadWrite; static const mode_t PermissionsMask_AllUsers_ReadWriteExecute; + public: static const UINT32 InvalidProcessId; static const SIZE_T InvalidThreadId; @@ -106,12 +108,12 @@ public: static void BuildSharedFilesPath(PathCharString& destination, const char *suffix, int suffixByteCount); static bool AppendUInt32String(PathCharString& destination, UINT32 value); - static bool EnsureDirectoryExists(const char *path, bool isGlobalLockAcquired, bool createIfNotExist = true, bool isSystemDirectory = false); + static bool EnsureDirectoryExists(const char *path, bool isGlobalLockAcquired, bool hasCurrentUserAccessOnly, bool setStickyFlag, bool createIfNotExist = true, bool isSystemDirectory = false); private: static int Open(LPCSTR path, int flags, mode_t mode = static_cast<mode_t>(0)); public: static int OpenDirectory(LPCSTR path); - static int CreateOrOpenFile(LPCSTR path, bool createIfNotExist = true, bool *createdRef = nullptr); + static int CreateOrOpenFile(LPCSTR path, bool createIfNotExist = true, bool isSessionScope = true, bool *createdRef = nullptr); static void CloseFile(int fileDescriptor); static SIZE_T GetFileSize(int fileDescriptor); diff --git a/src/coreclr/pal/src/sharedmemory/sharedmemory.cpp b/src/coreclr/pal/src/sharedmemory/sharedmemory.cpp index 9d7581788e9..12a3892c931 100644 --- a/src/coreclr/pal/src/sharedmemory/sharedmemory.cpp +++ b/src/coreclr/pal/src/sharedmemory/sharedmemory.cpp @@ -62,6 +62,7 @@ DWORD SharedMemoryException::GetErrorCode() const //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // SharedMemoryHelpers +const mode_t SharedMemoryHelpers::PermissionsMask_CurrentUser_ReadWrite = S_IRUSR | S_IWUSR; const mode_t SharedMemoryHelpers::PermissionsMask_CurrentUser_ReadWriteExecute = S_IRUSR | S_IWUSR | S_IXUSR; const mode_t SharedMemoryHelpers::PermissionsMask_AllUsers_ReadWrite = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; @@ -96,6 +97,8 @@ SIZE_T SharedMemoryHelpers::AlignUp(SIZE_T value, SIZE_T alignment) bool SharedMemoryHelpers::EnsureDirectoryExists( const char *path, bool isGlobalLockAcquired, + bool hasCurrentUserAccessOnly, + bool setStickyFlag, bool createIfNotExist, bool isSystemDirectory) { @@ -103,6 +106,13 @@ bool SharedMemoryHelpers::EnsureDirectoryExists( _ASSERTE(!(isSystemDirectory && createIfNotExist)); // should not create or change permissions on system directories _ASSERTE(SharedMemoryManager::IsCreationDeletionProcessLockAcquired()); _ASSERTE(!isGlobalLockAcquired || SharedMemoryManager::IsCreationDeletionFileLockAcquired()); + _ASSERTE(!(setStickyFlag && hasCurrentUserAccessOnly)); // Sticky bit doesn't make sense with current user access only + + mode_t mode = hasCurrentUserAccessOnly ? PermissionsMask_CurrentUser_ReadWriteExecute : PermissionsMask_AllUsers_ReadWriteExecute; + if (setStickyFlag) + { + mode |= S_ISVTX; + } // Check if the path already exists struct stat statInfo; @@ -123,11 +133,11 @@ bool SharedMemoryHelpers::EnsureDirectoryExists( if (isGlobalLockAcquired) { - if (mkdir(path, PermissionsMask_AllUsers_ReadWriteExecute) != 0) + if (mkdir(path, mode) != 0) { throw SharedMemoryException(static_cast<DWORD>(SharedMemoryError::IO)); } - if (chmod(path, PermissionsMask_AllUsers_ReadWriteExecute) != 0) + if (chmod(path, mode) != 0) { rmdir(path); throw SharedMemoryException(static_cast<DWORD>(SharedMemoryError::IO)); @@ -142,7 +152,7 @@ bool SharedMemoryHelpers::EnsureDirectoryExists( { throw SharedMemoryException(static_cast<DWORD>(SharedMemoryError::IO)); } - if (chmod(tempPath, PermissionsMask_AllUsers_ReadWriteExecute) != 0) + if (chmod(tempPath, mode) != 0) { rmdir(tempPath); throw SharedMemoryException(static_cast<DWORD>(SharedMemoryError::IO)); @@ -182,13 +192,18 @@ bool SharedMemoryHelpers::EnsureDirectoryExists( // For non-system directories (such as gSharedFilesPath/SHARED_MEMORY_RUNTIME_TEMP_DIRECTORY_NAME), // require sufficient permissions for all users and try to update them if requested to create the directory, so that // shared memory files may be shared by all processes on the system. - if ((statInfo.st_mode & PermissionsMask_AllUsers_ReadWriteExecute) == PermissionsMask_AllUsers_ReadWriteExecute) + if ((statInfo.st_mode & mode) == mode) { return true; } - if (!createIfNotExist || chmod(path, PermissionsMask_AllUsers_ReadWriteExecute) != 0) + if (!createIfNotExist || chmod(path, mode) != 0) { - throw SharedMemoryException(static_cast<DWORD>(SharedMemoryError::IO)); + // We were not asked to create the path or we weren't able to set the new permissions. + // As a last resort, check that at least the current user has full access. + if ((statInfo.st_mode & PermissionsMask_CurrentUser_ReadWriteExecute) != PermissionsMask_CurrentUser_ReadWriteExecute) + { + throw SharedMemoryException(static_cast<DWORD>(SharedMemoryError::IO)); + } } return true; } @@ -238,7 +253,7 @@ int SharedMemoryHelpers::OpenDirectory(LPCSTR path) return fileDescriptor; } -int SharedMemoryHelpers::CreateOrOpenFile(LPCSTR path, bool createIfNotExist, bool *createdRef) +int SharedMemoryHelpers::CreateOrOpenFile(LPCSTR path, bool createIfNotExist, bool isSessionScope, bool *createdRef) { _ASSERTE(path != nullptr); _ASSERTE(path[0] != '\0'); @@ -268,12 +283,13 @@ int SharedMemoryHelpers::CreateOrOpenFile(LPCSTR path, bool createIfNotExist, bo // File does not exist, create the file openFlags |= O_CREAT | O_EXCL; - fileDescriptor = Open(path, openFlags, PermissionsMask_AllUsers_ReadWrite); + mode_t mode = isSessionScope ? PermissionsMask_CurrentUser_ReadWrite : PermissionsMask_AllUsers_ReadWrite; + fileDescriptor = Open(path, openFlags, mode); _ASSERTE(fileDescriptor != -1); // The permissions mask passed to open() is filtered by the process' permissions umask, so open() may not set all of // the requested permissions. Use chmod() to set the proper permissions. - if (chmod(path, PermissionsMask_AllUsers_ReadWrite) != 0) + if (chmod(path, mode) != 0) { CloseFile(fileDescriptor); unlink(path); @@ -659,7 +675,7 @@ SharedMemoryProcessDataHeader *SharedMemoryProcessDataHeader::CreateOrOpen( SharedMemoryHelpers::VerifyStringOperation(SharedMemoryManager::CopySharedMemoryBasePath(filePath)); SharedMemoryHelpers::VerifyStringOperation(filePath.Append('/')); SharedMemoryHelpers::VerifyStringOperation(id.AppendSessionDirectoryName(filePath)); - if (!SharedMemoryHelpers::EnsureDirectoryExists(filePath, true /* isGlobalLockAcquired */, createIfNotExist)) + if (!SharedMemoryHelpers::EnsureDirectoryExists(filePath, true /* isGlobalLockAcquired */, id.IsSessionScope(), false /* setStickyFlag */, createIfNotExist)) { _ASSERTE(!createIfNotExist); return nullptr; @@ -672,7 +688,7 @@ SharedMemoryProcessDataHeader *SharedMemoryProcessDataHeader::CreateOrOpen( SharedMemoryHelpers::VerifyStringOperation(filePath.Append(id.GetName(), id.GetNameCharCount())); bool createdFile; - int fileDescriptor = SharedMemoryHelpers::CreateOrOpenFile(filePath, createIfNotExist, &createdFile); + int fileDescriptor = SharedMemoryHelpers::CreateOrOpenFile(filePath, createIfNotExist, id.IsSessionScope(), &createdFile); if (fileDescriptor == -1) { _ASSERTE(!createIfNotExist); @@ -1147,6 +1163,8 @@ void SharedMemoryManager::AcquireCreationDeletionFileLock() if (!SharedMemoryHelpers::EnsureDirectoryExists( *gSharedFilesPath, false /* isGlobalLockAcquired */, + false /* hasCurrentUserAccessOnly */, + true /* setStickyFlag */, false /* createIfNotExist */, true /* isSystemDirectory */)) { @@ -1154,10 +1172,14 @@ void SharedMemoryManager::AcquireCreationDeletionFileLock() } SharedMemoryHelpers::EnsureDirectoryExists( *s_runtimeTempDirectoryPath, - false /* isGlobalLockAcquired */); + false /* isGlobalLockAcquired */, + false /* hasCurrentUserAccessOnly */, + false /* setStickyFlag */); SharedMemoryHelpers::EnsureDirectoryExists( *s_sharedMemoryDirectoryPath, - false /* isGlobalLockAcquired */); + false /* isGlobalLockAcquired */, + false /* hasCurrentUserAccessOnly */, + true /* setStickyFlag */); s_creationDeletionLockFileDescriptor = SharedMemoryHelpers::OpenDirectory(*s_sharedMemoryDirectoryPath); if (s_creationDeletionLockFileDescriptor == -1) { diff --git a/src/coreclr/pal/src/synchobj/mutex.cpp b/src/coreclr/pal/src/synchobj/mutex.cpp index 267176b1511..f103ea818c4 100644 --- a/src/coreclr/pal/src/synchobj/mutex.cpp +++ b/src/coreclr/pal/src/synchobj/mutex.cpp @@ -1117,7 +1117,7 @@ SharedMemoryProcessDataHeader *NamedMutexProcessData::CreateOrOpen( SharedMemoryHelpers::BuildSharedFilesPath(lockFilePath, SHARED_MEMORY_LOCK_FILES_DIRECTORY_NAME); if (created) { - SharedMemoryHelpers::EnsureDirectoryExists(lockFilePath, true /* isGlobalLockAcquired */); + SharedMemoryHelpers::EnsureDirectoryExists(lockFilePath, true /* isGlobalLockAcquired */, false /* hasCurrentUserAccessOnly */, true /* setStickyFlag */); } // Create the session directory @@ -1126,7 +1126,7 @@ SharedMemoryProcessDataHeader *NamedMutexProcessData::CreateOrOpen( SharedMemoryHelpers::VerifyStringOperation(id->AppendSessionDirectoryName(lockFilePath)); if (created) { - SharedMemoryHelpers::EnsureDirectoryExists(lockFilePath, true /* isGlobalLockAcquired */); + SharedMemoryHelpers::EnsureDirectoryExists(lockFilePath, true /* isGlobalLockAcquired */, id->IsSessionScope(), false /* setStickyFlag */); autoCleanup.m_lockFilePath = &lockFilePath; autoCleanup.m_sessionDirectoryPathCharCount = lockFilePath.GetCount(); } @@ -1134,7 +1134,7 @@ SharedMemoryProcessDataHeader *NamedMutexProcessData::CreateOrOpen( // Create or open the lock file SharedMemoryHelpers::VerifyStringOperation(lockFilePath.Append('/')); SharedMemoryHelpers::VerifyStringOperation(lockFilePath.Append(id->GetName(), id->GetNameCharCount())); - int lockFileDescriptor = SharedMemoryHelpers::CreateOrOpenFile(lockFilePath, created); + int lockFileDescriptor = SharedMemoryHelpers::CreateOrOpenFile(lockFilePath, created, id->IsSessionScope()); if (lockFileDescriptor == -1) { _ASSERTE(!created); diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs index e36ae28fd43..fa5d77b2fdd 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs @@ -299,20 +299,16 @@ namespace Microsoft.Extensions.Configuration if (config != null && config.GetChildren().Any()) { - // for arrays, collections, and read-only list-like interfaces, we concatenate on to what is already there, if we can - if (type.IsArray || IsArrayCompatibleInterface(type)) + // for arrays and read-only list-like interfaces, we concatenate on to what is already there, if we can + if (type.IsArray || IsImmutableArrayCompatibleInterface(type)) { if (!bindingPoint.IsReadOnly) { bindingPoint.SetValue(BindArray(type, (IEnumerable?)bindingPoint.Value, config, options)); - return; } // for getter-only collection properties that we can't add to, nothing more we can do - if (type.IsArray || IsImmutableArrayCompatibleInterface(type)) - { - return; - } + return; } // for sets and read-only set interfaces, we clone what's there into a new collection, if we can @@ -350,12 +346,19 @@ namespace Microsoft.Extensions.Configuration return; } - // For other mutable interfaces like ICollection<> and ISet<>, we prefer copying values and setting them - // on a new instance of the interface over populating the existing instance implementing the interface. - // This has already been done, so there's not need to check again. For dictionaries, we fill the existing - // instance if there is one (which hasn't happened yet), and only create a new instance if necessary. + Type? interfaceGenericType = type.IsInterface && type.IsConstructedGenericType ? type.GetGenericTypeDefinition() : null; - bindingPoint.SetValue(CreateInstance(type, config, options)); + if (interfaceGenericType is not null && + (interfaceGenericType == typeof(ICollection<>) || interfaceGenericType == typeof(IList<>))) + { + // For ICollection<T> and IList<T> we bind them to mutable List<T> type. + Type genericType = typeof(List<>).MakeGenericType(type.GenericTypeArguments[0]); + bindingPoint.SetValue(Activator.CreateInstance(genericType)); + } + else + { + bindingPoint.SetValue(CreateInstance(type, config, options)); + } } // At this point we know that we have a non-null bindingPoint.Value, we just have to populate the items @@ -554,9 +557,9 @@ namespace Microsoft.Extensions.Configuration // Binds and potentially overwrites a concrete dictionary. // This differs from BindDictionaryInterface because this method doesn't clone // the dictionary; it sets and/or overwrites values directly. - // When a user specifies a concrete dictionary in their config class, then that - // value is used as-us. When a user specifies an interface (instantiated) in their config class, - // then it is cloned to a new dictionary, the same way as other collections. + // When a user specifies a concrete dictionary or a concrete class implementing IDictionary<,> + // in their config class, then that value is used as-is. When a user specifies an interface (instantiated) + // in their config class, then it is cloned to a new dictionary, the same way as other collections. [RequiresDynamicCode(DynamicCodeWarningMessage)] [RequiresUnreferencedCode("Cannot statically analyze what the element type is of the value objects in the dictionary so its members may be trimmed.")] private static void BindConcreteDictionary( @@ -584,10 +587,20 @@ namespace Microsoft.Extensions.Configuration return; } - Type genericType = typeof(Dictionary<,>).MakeGenericType(keyType, valueType); + Debug.Assert(dictionary is not null); + + Type dictionaryObjectType = dictionary.GetType(); + + MethodInfo tryGetValue = dictionaryObjectType.GetMethod("TryGetValue", BindingFlags.Public | BindingFlags.Instance)!; + + // dictionary should be of type Dictionary<,> or of type implementing IDictionary<,> + PropertyInfo? setter = dictionaryObjectType.GetProperty("Item", BindingFlags.Public | BindingFlags.Instance); + if (setter is null || !setter.CanWrite) + { + // Cannot set any item on the dictionary object. + return; + } - MethodInfo tryGetValue = dictionaryType.GetMethod("TryGetValue")!; - PropertyInfo setter = genericType.GetProperty("Item", DeclaredOnlyLookup)!; foreach (IConfigurationSection child in config.GetChildren()) { try @@ -838,18 +851,6 @@ namespace Microsoft.Extensions.Configuration || genericTypeDefinition == typeof(IReadOnlyDictionary<,>); } - private static bool IsArrayCompatibleInterface(Type type) - { - if (!type.IsInterface || !type.IsConstructedGenericType) { return false; } - - Type genericTypeDefinition = type.GetGenericTypeDefinition(); - return genericTypeDefinition == typeof(IEnumerable<>) - || genericTypeDefinition == typeof(ICollection<>) - || genericTypeDefinition == typeof(IList<>) - || genericTypeDefinition == typeof(IReadOnlyCollection<>) - || genericTypeDefinition == typeof(IReadOnlyList<>); - } - private static bool IsImmutableArrayCompatibleInterface(Type type) { if (!type.IsInterface || !type.IsConstructedGenericType) { return false; } diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/src/Microsoft.Extensions.Configuration.Binder.csproj b/src/libraries/Microsoft.Extensions.Configuration.Binder/src/Microsoft.Extensions.Configuration.Binder.csproj index f5517f57f23..55eba74864b 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/src/Microsoft.Extensions.Configuration.Binder.csproj +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/src/Microsoft.Extensions.Configuration.Binder.csproj @@ -5,6 +5,8 @@ <EnableDefaultItems>true</EnableDefaultItems> <IsPackable>true</IsPackable> <EnableAOTAnalyzer>true</EnableAOTAnalyzer> + <GeneratePackageOnBuild>true</GeneratePackageOnBuild> + <ServicingVersion>1</ServicingVersion> <PackageDescription>Functionality to bind an object to data in configuration providers for Microsoft.Extensions.Configuration.</PackageDescription> </PropertyGroup> diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/ConfigurationCollectionBindingTests.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/ConfigurationCollectionBindingTests.cs index 4f2b5911b2b..66bc1402bdd 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/ConfigurationCollectionBindingTests.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/ConfigurationCollectionBindingTests.cs @@ -393,6 +393,11 @@ namespace Microsoft.Extensions.Configuration.Binder.Test Assert.Equal("val1", list[2]); Assert.Equal("val2", list[3]); Assert.Equal("valx", list[4]); + + // Ensure expandability of the returned list + options.AlreadyInitializedListInterface.Add("ExtraItem"); + Assert.Equal(6, options.AlreadyInitializedListInterface.Count); + Assert.Equal("ExtraItem", options.AlreadyInitializedListInterface[5]); } [Fact] @@ -1067,7 +1072,7 @@ namespace Microsoft.Extensions.Configuration.Binder.Test {"AlreadyInitializedIEnumerableInterface:1", "val1"}, {"AlreadyInitializedIEnumerableInterface:2", "val2"}, {"AlreadyInitializedIEnumerableInterface:x", "valx"}, - + {"ICollectionNoSetter:0", "val0"}, {"ICollectionNoSetter:1", "val1"}, }; @@ -1098,6 +1103,11 @@ namespace Microsoft.Extensions.Configuration.Binder.Test Assert.Equal(2, options.ICollectionNoSetter.Count); Assert.Equal("val0", options.ICollectionNoSetter.ElementAt(0)); Assert.Equal("val1", options.ICollectionNoSetter.ElementAt(1)); + + // Ensure expandability of the returned collection + options.ICollectionNoSetter.Add("ExtraItem"); + Assert.Equal(3, options.ICollectionNoSetter.Count); + Assert.Equal("ExtraItem", options.ICollectionNoSetter.ElementAt(2)); } [Fact] @@ -1218,6 +1228,11 @@ namespace Microsoft.Extensions.Configuration.Binder.Test Assert.Equal("val1", array[1]); Assert.Equal("val2", array[2]); Assert.Equal("valx", array[3]); + + // Ensure expandability of the returned collection + options.ICollection.Add("ExtraItem"); + Assert.Equal(5, options.ICollection.Count); + Assert.Equal("ExtraItem", options.ICollection.ElementAt(4)); } [Fact] @@ -1246,6 +1261,11 @@ namespace Microsoft.Extensions.Configuration.Binder.Test Assert.Equal("val1", list[1]); Assert.Equal("val2", list[2]); Assert.Equal("valx", list[3]); + + // Ensure expandability of the returned list + options.IList.Add("ExtraItem"); + Assert.Equal(5, options.IList.Count); + Assert.Equal("ExtraItem", options.IList[4]); } [Fact] @@ -1602,5 +1622,61 @@ namespace Microsoft.Extensions.Configuration.Binder.Test public IEnumerable<int> FilteredConfigValues => ConfigValues.Where(p => p > 10); public IEnumerable<int> ConfigValues { get; set; } } + + [Fact] + public void DifferentDictionaryBindingCasesTest() + { + var dic = new Dictionary<string, string>() { { "key", "value" } }; + var config = new ConfigurationBuilder() + .AddInMemoryCollection(dic) + .Build(); + + Assert.Single(config.Get<Dictionary<string, string>>()); + Assert.Single(config.Get<IDictionary<string, string>>()); + Assert.Single(config.Get<ExtendedDictionary<string, string>>()); + Assert.Single(config.Get<ImplementerOfIDictionaryClass<string, string>>()); + } + + public class ImplementerOfIDictionaryClass<TKey, TValue> : IDictionary<TKey, TValue> + { + private Dictionary<TKey, TValue> _dict = new(); + + public TValue this[TKey key] { get => _dict[key]; set => _dict[key] = value; } + + public ICollection<TKey> Keys => _dict.Keys; + + public ICollection<TValue> Values => _dict.Values; + + public int Count => _dict.Count; + + public bool IsReadOnly => false; + + public void Add(TKey key, TValue value) => _dict.Add(key, value); + + public void Add(KeyValuePair<TKey, TValue> item) => _dict.Add(item.Key, item.Value); + + public void Clear() => _dict.Clear(); + + public bool Contains(KeyValuePair<TKey, TValue> item) => _dict.Contains(item); + + public bool ContainsKey(TKey key) => _dict.ContainsKey(key); + + public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex) => throw new NotImplementedException(); + + public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() => _dict.GetEnumerator(); + + public bool Remove(TKey key) => _dict.Remove(key); + + public bool Remove(KeyValuePair<TKey, TValue> item) => _dict.Remove(item.Key); + + public bool TryGetValue(TKey key, out TValue value) => _dict.TryGetValue(key, out value); + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => _dict.GetEnumerator(); + } + + public class ExtendedDictionary<TKey, TValue> : Dictionary<TKey, TValue> + { + + } } } diff --git a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarEntry.cs b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarEntry.cs index a27df41f4c1..5c08ec75f74 100644 --- a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarEntry.cs +++ b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarEntry.cs @@ -138,10 +138,12 @@ namespace System.Formats.Tar /// <remarks>The value in this field has no effect on Windows platforms.</remarks> public UnixFileMode Mode { - get => (UnixFileMode)_header._mode; + // Some paths do not use the setter, and we want to return valid UnixFileMode. + // This mask only keeps the least significant 12 bits. + get => (UnixFileMode)(_header._mode & (int)TarHelpers.ValidUnixFileModes); set { - if ((int)value is < 0 or > 4095) // 4095 in decimal is 7777 in octal + if ((value & ~TarHelpers.ValidUnixFileModes) != 0) // throw on invalid UnixFileModes { throw new ArgumentOutOfRangeException(nameof(value)); } diff --git a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHelpers.cs b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHelpers.cs index d5393b45ffc..45cae1c2759 100644 --- a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHelpers.cs +++ b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHelpers.cs @@ -21,6 +21,20 @@ namespace System.Formats.Tar internal const int MaxBufferLength = 4096; internal const long MaxSizeLength = (1L << 33) - 1; // Max value of 11 octal digits = 2^33 - 1 or 8 Gb. + internal const UnixFileMode ValidUnixFileModes = + UnixFileMode.UserRead | + UnixFileMode.UserWrite | + UnixFileMode.UserExecute | + UnixFileMode.GroupRead | + UnixFileMode.GroupWrite | + UnixFileMode.GroupExecute | + UnixFileMode.OtherRead | + UnixFileMode.OtherWrite | + UnixFileMode.OtherExecute | + UnixFileMode.StickyBit | + UnixFileMode.SetGroup | + UnixFileMode.SetUser; + // Default mode for TarEntry created for a file-type. private const UnixFileMode DefaultFileMode = UnixFileMode.UserRead | UnixFileMode.UserWrite | diff --git a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarWriter.Unix.cs b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarWriter.Unix.cs index a691582178d..357e4a8a758 100644 --- a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarWriter.Unix.cs +++ b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarWriter.Unix.cs @@ -66,7 +66,8 @@ namespace System.Formats.Tar entry._header._aTime = TarHelpers.GetDateTimeOffsetFromSecondsSinceEpoch(status.ATime); entry._header._cTime = TarHelpers.GetDateTimeOffsetFromSecondsSinceEpoch(status.CTime); - entry._header._mode = status.Mode & 4095; // First 12 bits + // This mask only keeps the least significant 12 bits valid for UnixFileModes + entry._header._mode = status.Mode & (int)TarHelpers.ValidUnixFileModes; // Uid and UName entry._header._uid = (int)status.Uid; diff --git a/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectoryAsync.Stream.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectoryAsync.Stream.Tests.cs index 70c6fcbf804..82c37fb0dd0 100644 --- a/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectoryAsync.Stream.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectoryAsync.Stream.Tests.cs @@ -97,6 +97,19 @@ namespace System.Formats.Tar.Tests } } + [Fact] + public async Task ExtractEntry_DockerImageTarWithFileTypeInDirectoriesInMode_SuccessfullyExtracts_Async() + { + using (TempDirectory root = new TempDirectory()) + { + await using MemoryStream archiveStream = GetTarMemoryStream(CompressionMethod.Uncompressed, "golang_tar", "docker-hello-world"); + await TarFile.ExtractToDirectoryAsync(archiveStream, root.Path, overwriteFiles: true); + + Assert.True(File.Exists(Path.Join(root.Path, "manifest.json"))); + Assert.True(File.Exists(Path.Join(root.Path, "repositories"))); + } + } + [Theory] [InlineData(TarEntryType.SymbolicLink)] [InlineData(TarEntryType.HardLink)] diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/IncrementalGeneratorInitializationContextExtensions.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/IncrementalGeneratorInitializationContextExtensions.cs index 0b008795884..20a1818a33e 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/IncrementalGeneratorInitializationContextExtensions.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/IncrementalGeneratorInitializationContextExtensions.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.Linq; using System.Text; using Microsoft.CodeAnalysis; @@ -27,12 +28,21 @@ namespace Microsoft.Interop public static void RegisterConcatenatedSyntaxOutputs<TNode>(this IncrementalGeneratorInitializationContext context, IncrementalValuesProvider<TNode> nodes, string fileName) where TNode : SyntaxNode { - IncrementalValueProvider<string> generatedMethods = nodes + IncrementalValueProvider<ImmutableArray<string>> generatedMethods = nodes .Select( static (node, ct) => node.NormalizeWhitespace().ToFullString()) - .Collect() - .Select(static (generatedSources, ct) => + .Collect(); + + context.RegisterSourceOutput(generatedMethods, + (context, generatedSources) => { + // Don't generate a file if we don't have to, to avoid the extra IDE overhead once we have generated + // files in play. + if (generatedSources.IsEmpty) + { + return; + } + StringBuilder source = new(); // Mark in source that the file is auto-generated. source.AppendLine("// <auto-generated/>"); @@ -40,13 +50,9 @@ namespace Microsoft.Interop { source.AppendLine(generated); } - return source.ToString(); - }); - context.RegisterSourceOutput(generatedMethods, - (context, source) => - { - context.AddSource(fileName, source); + // Once https://github.com/dotnet/roslyn/issues/61326 is resolved, we can avoid the ToString() here. + context.AddSource(fileName, source.ToString()); }); } } diff --git a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/Compiles.cs b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/Compiles.cs index f23a9f22c61..17ba7dea250 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/Compiles.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/Compiles.cs @@ -641,33 +641,30 @@ namespace LibraryImportGenerator.UnitTests TestUtils.AssertPostSourceGeneratorCompilation(newComp); } - public static IEnumerable<object[]> CodeSnippetsToCompileToValidateAllowUnsafeBlocks() + public static IEnumerable<object[]> CodeSnippetsToVerifyNoTreesProduced() { - yield return new object[] { ID(), CodeSnippets.TrivialClassDeclarations, TestTargetFramework.Net, true }; - - { - string source = @" + string source = @" using System.Runtime.InteropServices; public class Basic { } "; - yield return new object[] { ID(), source, TestTargetFramework.Standard, false }; - yield return new object[] { ID(), source, TestTargetFramework.Framework, false }; - yield return new object[] { ID(), source, TestTargetFramework.Net, false }; - } + yield return new object[] { ID(), source, TestTargetFramework.Standard }; + yield return new object[] { ID(), source, TestTargetFramework.Framework }; + yield return new object[] { ID(), source, TestTargetFramework.Net }; } [Theory] - [MemberData(nameof(CodeSnippetsToCompileToValidateAllowUnsafeBlocks))] - public async Task ValidateRequireAllowUnsafeBlocksDiagnosticNoTrigger(string id, string source, TestTargetFramework framework, bool allowUnsafe) + [MemberData(nameof(CodeSnippetsToVerifyNoTreesProduced))] + public async Task ValidateNoGeneratedOuptutForNoImport(string id, string source, TestTargetFramework framework) { TestUtils.Use(id); - Compilation comp = await TestUtils.CreateCompilation(source, framework, allowUnsafe: allowUnsafe); + Compilation comp = await TestUtils.CreateCompilation(source, framework, allowUnsafe: false); TestUtils.AssertPreSourceGeneratorCompilation(comp); var newComp = TestUtils.RunGenerators(comp, out var generatorDiags, new Microsoft.Interop.LibraryImportGenerator()); Assert.Empty(generatorDiags); - TestUtils.AssertPostSourceGeneratorCompilation(newComp); + // Assert we didn't generate any syntax trees, even empty ones + Assert.Same(comp, newComp); } } } diff --git a/src/mono/mono/mini/interp/interp.c b/src/mono/mono/mini/interp/interp.c index b89f8a7a181..89a0b5962e3 100644 --- a/src/mono/mono/mini/interp/interp.c +++ b/src/mono/mono/mini/interp/interp.c @@ -94,6 +94,7 @@ struct FrameClauseArgs { const guint16 *end_at_ip; /* Frame that is executing this clause */ InterpFrame *exec_frame; + gboolean run_until_end; }; /* @@ -3595,6 +3596,13 @@ interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClauseArgs INIT_INTERP_STATE (frame, clause_args); + if (clause_args && clause_args->run_until_end) + /* + * Called from run_with_il_state to run the method until the end. + * Clear this out so it doesn't confuse the rest of the code. + */ + clause_args = NULL; + #ifdef ENABLE_EXPERIMENT_TIERED mini_tiered_inc (frame->imethod->method, &frame->imethod->tiered_counter, 0); #endif @@ -7067,7 +7075,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; MINT_IN_CASE(MINT_TIER_ENTER_METHOD) { frame->imethod->entry_count++; - if (frame->imethod->entry_count > INTERP_TIER_ENTRY_LIMIT) + if (frame->imethod->entry_count > INTERP_TIER_ENTRY_LIMIT && !clause_args) ip = mono_interp_tier_up_frame_enter (frame, context); else ip++; @@ -7075,7 +7083,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; } MINT_IN_CASE(MINT_TIER_PATCHPOINT) { frame->imethod->entry_count++; - if (frame->imethod->entry_count > INTERP_TIER_ENTRY_LIMIT) + if (frame->imethod->entry_count > INTERP_TIER_ENTRY_LIMIT && !clause_args) ip = mono_interp_tier_up_frame_patchpoint (frame, context, ip [1]); else ip += 2; @@ -7656,10 +7664,13 @@ interp_run_clause_with_il_state (gpointer il_state_ptr, int clause_index, MonoOb clause_args.start_with_ip = (const guint16*)ei->data.filter; else clause_args.start_with_ip = (const guint16*)ei->handler_start; - if (clause_type == MONO_EXCEPTION_CLAUSE_NONE || clause_type == MONO_EXCEPTION_CLAUSE_FILTER) - clause_args.end_at_ip = (const guint16*)clause_args.start_with_ip + 0xffffff; - else + if (clause_type == MONO_EXCEPTION_CLAUSE_NONE || clause_type == MONO_EXCEPTION_CLAUSE_FILTER) { + /* Run until the end */ + clause_args.end_at_ip = NULL; + clause_args.run_until_end = TRUE; + } else { clause_args.end_at_ip = (const guint16*)ei->data.handler_end; + } clause_args.exec_frame = &frame; if (clause_type == MONO_EXCEPTION_CLAUSE_NONE || clause_type == MONO_EXCEPTION_CLAUSE_FILTER) diff --git a/src/mono/mono/mini/mini-ppc.c b/src/mono/mono/mini/mini-ppc.c index db669f8b5da..73a26c02b18 100644 --- a/src/mono/mono/mini/mini-ppc.c +++ b/src/mono/mono/mini/mini-ppc.c @@ -470,10 +470,54 @@ mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_targe return start; } +/** + * + * @brief Architecture-specific delegation virtual trampoline processing + * + * @param[in] @sig - Method signature + * @param[in] @method - Method + * @param[in] @offset - Offset into vtable + * @param[in] @load_imt_reg - Whether to load the LMT register + * @returns Trampoline + * + * Return a pointer to a delegation virtual trampoline + */ + gpointer mono_arch_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod *method, int offset, gboolean load_imt_reg) { - return NULL; + guint8 *code, *start; + int size = 32; + + start = code = (guint8 *) mono_global_codeman_reserve (size); + + /* + * Replace the "this" argument with the target + */ + ppc_mr (code, ppc_r12, ppc_r3); + ppc_ldptr (code, ppc_r3, MONO_STRUCT_OFFSET(MonoDelegate, target), ppc_r12); + + /* + * Load the IMT register, if needed + */ + if (load_imt_reg) { + ppc_ldptr (code, MONO_ARCH_IMT_REG, MONO_STRUCT_OFFSET(MonoDelegate, method), ppc_r12); + } + + /* + * Load the vTable + */ + ppc_ldptr (code, ppc_r12, MONO_STRUCT_OFFSET(MonoObject, vtable), ppc_r3); + if (!ppc_is_imm16(offset)) + ppc_addis (code, ppc_r12, ppc_r12, ppc_ha(offset)); + ppc_ldptr (code, ppc_r12, offset, ppc_r12); + ppc_mtctr (code, ppc_r12); + ppc_bcctr (code, PPC_BR_ALWAYS, 0); + + mono_arch_flush_icache (start, code - start); + MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE, NULL)); + + return(start); } gpointer diff --git a/src/mono/mono/utils/memfuncs.c b/src/mono/mono/utils/memfuncs.c index 885c21ae3d8..a38dcec17b1 100644 --- a/src/mono/mono/utils/memfuncs.c +++ b/src/mono/mono/utils/memfuncs.c @@ -70,7 +70,7 @@ __d [__i] = NULL; \ } while (0) -#define MINMEMSZ 209715200 /* Minimum restricted memory size */ +#define MINMEMSZ 20971520 /* Minimum restricted memory size - 20MB */ /** * mono_gc_bzero_aligned: diff --git a/src/native/libs/System.Security.Cryptography.Native.Apple/pal_keychain_macos.c b/src/native/libs/System.Security.Cryptography.Native.Apple/pal_keychain_macos.c index 92ed4c00f03..b89bcce3517 100644 --- a/src/native/libs/System.Security.Cryptography.Native.Apple/pal_keychain_macos.c +++ b/src/native/libs/System.Security.Cryptography.Native.Apple/pal_keychain_macos.c @@ -16,7 +16,10 @@ int32_t AppleCryptoNative_SecKeychainItemCopyKeychain(SecKeychainItemRef item, S if (itemType == SecKeyGetTypeID() || itemType == SecIdentityGetTypeID() || itemType == SecCertificateGetTypeID()) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" OSStatus status = SecKeychainItemCopyKeychain(item, pKeychainOut); +#pragma clang diagnostic pop if (status == noErr) { @@ -40,12 +43,18 @@ int32_t AppleCryptoNative_SecKeychainCreate(const char* pathName, const uint8_t* passphraseUtf8, SecKeychainRef* pKeychainOut) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" return SecKeychainCreate(pathName, passphraseLength, passphraseUtf8, false, NULL, pKeychainOut); +#pragma clang diagnostic pop } int32_t AppleCryptoNative_SecKeychainDelete(SecKeychainRef keychain) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" return SecKeychainDelete(keychain); +#pragma clang diagnostic pop } int32_t AppleCryptoNative_SecKeychainCopyDefault(SecKeychainRef* pKeychainOut) @@ -53,7 +62,10 @@ int32_t AppleCryptoNative_SecKeychainCopyDefault(SecKeychainRef* pKeychainOut) if (pKeychainOut != NULL) *pKeychainOut = NULL; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" return SecKeychainCopyDefault(pKeychainOut); +#pragma clang diagnostic pop } int32_t AppleCryptoNative_SecKeychainOpen(const char* pszKeychainPath, SecKeychainRef* pKeychainOut) @@ -64,12 +76,18 @@ int32_t AppleCryptoNative_SecKeychainOpen(const char* pszKeychainPath, SecKeycha if (pszKeychainPath == NULL) return errSecParam; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" return SecKeychainOpen(pszKeychainPath, pKeychainOut); +#pragma clang diagnostic pop } int32_t AppleCryptoNative_SecKeychainUnlock(SecKeychainRef keychain, uint32_t passphraseLength, const uint8_t* passphraseUtf8) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" return SecKeychainUnlock(keychain, passphraseLength, passphraseUtf8, true); +#pragma clang diagnostic pop } int32_t AppleCryptoNative_SetKeychainNeverLock(SecKeychainRef keychain) @@ -81,7 +99,10 @@ int32_t AppleCryptoNative_SetKeychainNeverLock(SecKeychainRef keychain) .lockInterval = INT_MAX, }; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" return SecKeychainSetSettings(keychain, &settings); +#pragma clang diagnostic pop } static int32_t @@ -262,7 +283,7 @@ static bool IsCertInKeychain(CFTypeRef needle, SecKeychainRef haystack) { ret = false; } - + if (result != NULL) { CFRelease(result); @@ -355,7 +376,10 @@ int32_t AppleCryptoNative_X509StoreAddCertificate(CFTypeRef certOrIdentity, SecK // keychain back to disk. if (status == noErr && privateKey != NULL) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" status = SecKeychainItemCreateCopy((SecKeychainItemRef)privateKey, keychain, NULL, &itemCopy); +#pragma clang diagnostic pop } if (status == errSecDuplicateItem) @@ -374,7 +398,10 @@ int32_t AppleCryptoNative_X509StoreAddCertificate(CFTypeRef certOrIdentity, SecK if (status == noErr && cert != NULL) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" status = SecKeychainItemCreateCopy((SecKeychainItemRef)cert, keychain, NULL, &itemCopy); +#pragma clang diagnostic pop } if (status == errSecDuplicateItem) diff --git a/src/native/libs/System.Security.Cryptography.Native.Apple/pal_x509_macos.c b/src/native/libs/System.Security.Cryptography.Native.Apple/pal_x509_macos.c index a396ec7f649..41ba9648259 100644 --- a/src/native/libs/System.Security.Cryptography.Native.Apple/pal_x509_macos.c +++ b/src/native/libs/System.Security.Cryptography.Native.Apple/pal_x509_macos.c @@ -384,8 +384,10 @@ int32_t AppleCryptoNative_X509CopyWithPrivateKey(SecCertificateRef cert, } SecKeychainRef keyKeychain = NULL; - +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" OSStatus status = SecKeychainItemCopyKeychain((SecKeychainItemRef)privateKey, &keyKeychain); +#pragma clang diagnostic pop SecKeychainItemRef itemCopy = NULL; // This only happens with an ephemeral key, so the keychain we're adding it to is temporary. @@ -536,7 +538,10 @@ int32_t AppleCryptoNative_X509MoveToKeychain(SecCertificateRef cert, SecKeychainRef curKeychain = NULL; SecKeyRef importedKey = NULL; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" OSStatus status = SecKeychainItemCopyKeychain((SecKeychainItemRef)cert, &curKeychain); +#pragma clang diagnostic pop if (status == errSecNoSuchKeychain) { @@ -559,7 +564,10 @@ int32_t AppleCryptoNative_X509MoveToKeychain(SecCertificateRef cert, if (status == noErr && privateKey != NULL) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" status = SecKeychainItemCopyKeychain((SecKeychainItemRef)privateKey, &curKeychain); +#pragma clang diagnostic pop if (status == errSecNoSuchKeychain) { |