Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/dotnet/runtime.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Sanchez <1175054+carlossanlop@users.noreply.github.com>2022-11-11 05:45:06 +0300
committerGitHub <noreply@github.com>2022-11-11 05:45:06 +0300
commitef994e48ea3e4b7aa650d0d6cc6421b0726f6ce0 (patch)
treec6be104666da9cb2bf673a846ca981e1f68dd7a1
parentaebb541ea46e4350764b8975dfffa92b88eac7c7 (diff)
parent9dd2bbcfa46fa4650379ceeba7781f41cfc0e273 (diff)
Merge branch 'release/7.0' into darc-release/7.0-88d4fa90-5b62-4f24-9b34-817e68929c2adarc-release/7.0-88d4fa90-5b62-4f24-9b34-817e68929c2a
-rw-r--r--NuGet.config1
-rw-r--r--eng/Version.Details.xml8
-rw-r--r--eng/Versions.props4
-rw-r--r--src/coreclr/jit/emit.h14
-rw-r--r--src/coreclr/jit/emitarm64.cpp13
-rw-r--r--src/coreclr/jit/emitxarch.cpp28
-rw-r--r--src/coreclr/pal/src/include/pal/sharedmemory.h6
-rw-r--r--src/coreclr/pal/src/sharedmemory/sharedmemory.cpp48
-rw-r--r--src/coreclr/pal/src/synchobj/mutex.cpp6
-rw-r--r--src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs61
-rw-r--r--src/libraries/Microsoft.Extensions.Configuration.Binder/src/Microsoft.Extensions.Configuration.Binder.csproj2
-rw-r--r--src/libraries/Microsoft.Extensions.Configuration.Binder/tests/ConfigurationCollectionBindingTests.cs78
-rw-r--r--src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarEntry.cs6
-rw-r--r--src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHelpers.cs14
-rw-r--r--src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarWriter.Unix.cs3
-rw-r--r--src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectoryAsync.Stream.Tests.cs13
-rw-r--r--src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/IncrementalGeneratorInitializationContextExtensions.cs24
-rw-r--r--src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/Compiles.cs23
-rw-r--r--src/mono/mono/mini/interp/interp.c21
-rw-r--r--src/mono/mono/mini/mini-ppc.c46
-rw-r--r--src/mono/mono/utils/memfuncs.c2
-rw-r--r--src/native/libs/System.Security.Cryptography.Native.Apple/pal_keychain_macos.c29
-rw-r--r--src/native/libs/System.Security.Cryptography.Native.Apple/pal_x509_macos.c10
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)
{